From 2ac7b44fb61507fbc7cc3cd99d6e2f9f81ab895d Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 12:43:35 -0700 Subject: [PATCH 01/12] Derive license reports and SBOMs from build evidence via cargo tree Classify every compiled crate as runtime or build-time using Cargo's own resolver (`cargo tree`), cross-checked against the build log, and approve the result against the allow-list instead of filtering with it. - input/: readers that turn one target's evidence (build log + full and runtime `cargo tree`) into a format-neutral TargetGraph (graph.rs) - inventory.rs: merge targets (runtime wins), resolve against the cargo metadata dictionary, normalize declared licenses once, `embedded` - approval.rs: every crate in exactly one list, build-only crates may not ship, reviewed licenses checked against the declared SPDX expression - sbom.rs + gen-sbom-log[-dir]: CycloneDX 1.5 output - gen-licenses-log[-dir] now take --root-package and per-target directories with build.json, tree.txt and runtime-tree.txt - Apache-2.0 license, `embedded` and `commercial_license` config fields - tests: unit tests, a fixture workspace built with the installed Cargo, golden tests on real dnp3 evidence, and a regression test that the deprecated cargo-cyclonedx commands still match 0.2.1 output --- Cargo.lock | 62 + allow-list/Cargo.toml | 3 + allow-list/licenses/apache2.txt | 178 + allow-list/src/approval.rs | 382 + allow-list/src/cli.rs | 149 +- allow-list/src/commands.rs | 128 + allow-list/src/config.rs | 34 + allow-list/src/fixture_tests.rs | 255 + allow-list/src/golden_tests.rs | 426 ++ allow-list/src/graph.rs | 166 + allow-list/src/input/build_log.rs | 237 + allow-list/src/input/cargo_tree.rs | 231 + allow-list/src/input/mod.rs | 177 + allow-list/src/input/pkgid.rs | 92 + allow-list/src/inventory.rs | 394 + allow-list/src/licenses.rs | 26 + allow-list/src/log.rs | 123 - allow-list/src/main.rs | 45 +- allow-list/src/sbom.rs | 225 + .../tests/fixtures/cyclonedx/a/bom.json | 1 + .../tests/fixtures/cyclonedx/allowed.json | 9 + .../tests/fixtures/cyclonedx/b/bom.json | 1 + .../tests/fixtures/cyclonedx/expected-dir.txt | 84 + .../fixtures/cyclonedx/expected-single.txt | 78 + allow-list/tests/fixtures/dnp3/Cargo.lock | 1326 ++++ allow-list/tests/fixtures/dnp3/allowed.json | 2071 +++++ allow-list/tests/fixtures/dnp3/metadata.json | 6723 +++++++++++++++++ .../fixtures/dnp3/targets/aws/build.json | 175 + .../dnp3/targets/aws/runtime-tree.txt | 159 + .../tests/fixtures/dnp3/targets/aws/tree.txt | 263 + .../fixtures/dnp3/targets/ring/build.json | 170 + .../dnp3/targets/ring/runtime-tree.txt | 162 + .../tests/fixtures/dnp3/targets/ring/tree.txt | 258 + .../tests/fixtures/workspace/Cargo.lock | 60 + .../tests/fixtures/workspace/Cargo.toml | 5 + .../workspace/alias-target/Cargo.toml | 9 + .../workspace/alias-target/src/lib.rs | 1 + .../tests/fixtures/workspace/app/Cargo.toml | 29 + .../tests/fixtures/workspace/app/build.rs | 3 + .../tests/fixtures/workspace/app/src/lib.rs | 8 + .../fixtures/workspace/common/Cargo.toml | 6 + .../fixtures/workspace/common/src/lib.rs | 1 + .../fixtures/workspace/optdep/Cargo.toml | 6 + .../fixtures/workspace/optdep/src/lib.rs | 1 + .../tests/fixtures/workspace/pm/Cargo.toml | 13 + .../tests/fixtures/workspace/pm/src/lib.rs | 8 + .../fixtures/workspace/pmonly/Cargo.toml | 6 + .../fixtures/workspace/pmonly/src/lib.rs | 1 + .../fixtures/workspace/shared/Cargo.toml | 9 + .../fixtures/workspace/shared/src/lib.rs | 1 + .../tests/fixtures/workspace/tool/Cargo.toml | 8 + .../tests/fixtures/workspace/tool/src/lib.rs | 1 + .../fixtures/workspace/unixonly/Cargo.toml | 6 + .../fixtures/workspace/unixonly/src/lib.rs | 1 + .../fixtures/workspace/winonly/Cargo.toml | 6 + .../fixtures/workspace/winonly/src/lib.rs | 1 + 56 files changed, 14841 insertions(+), 162 deletions(-) create mode 100644 allow-list/licenses/apache2.txt create mode 100644 allow-list/src/approval.rs create mode 100644 allow-list/src/commands.rs create mode 100644 allow-list/src/fixture_tests.rs create mode 100644 allow-list/src/golden_tests.rs create mode 100644 allow-list/src/graph.rs create mode 100644 allow-list/src/input/build_log.rs create mode 100644 allow-list/src/input/cargo_tree.rs create mode 100644 allow-list/src/input/mod.rs create mode 100644 allow-list/src/input/pkgid.rs create mode 100644 allow-list/src/inventory.rs delete mode 100644 allow-list/src/log.rs create mode 100644 allow-list/src/sbom.rs create mode 100644 allow-list/tests/fixtures/cyclonedx/a/bom.json create mode 100644 allow-list/tests/fixtures/cyclonedx/allowed.json create mode 100644 allow-list/tests/fixtures/cyclonedx/b/bom.json create mode 100644 allow-list/tests/fixtures/cyclonedx/expected-dir.txt create mode 100644 allow-list/tests/fixtures/cyclonedx/expected-single.txt create mode 100644 allow-list/tests/fixtures/dnp3/Cargo.lock create mode 100644 allow-list/tests/fixtures/dnp3/allowed.json create mode 100644 allow-list/tests/fixtures/dnp3/metadata.json create mode 100644 allow-list/tests/fixtures/dnp3/targets/aws/build.json create mode 100644 allow-list/tests/fixtures/dnp3/targets/aws/runtime-tree.txt create mode 100644 allow-list/tests/fixtures/dnp3/targets/aws/tree.txt create mode 100644 allow-list/tests/fixtures/dnp3/targets/ring/build.json create mode 100644 allow-list/tests/fixtures/dnp3/targets/ring/runtime-tree.txt create mode 100644 allow-list/tests/fixtures/dnp3/targets/ring/tree.txt create mode 100644 allow-list/tests/fixtures/workspace/Cargo.lock create mode 100644 allow-list/tests/fixtures/workspace/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/alias-target/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/alias-target/src/lib.rs create mode 100644 allow-list/tests/fixtures/workspace/app/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/app/build.rs create mode 100644 allow-list/tests/fixtures/workspace/app/src/lib.rs create mode 100644 allow-list/tests/fixtures/workspace/common/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/common/src/lib.rs create mode 100644 allow-list/tests/fixtures/workspace/optdep/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/optdep/src/lib.rs create mode 100644 allow-list/tests/fixtures/workspace/pm/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/pm/src/lib.rs create mode 100644 allow-list/tests/fixtures/workspace/pmonly/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/pmonly/src/lib.rs create mode 100644 allow-list/tests/fixtures/workspace/shared/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/shared/src/lib.rs create mode 100644 allow-list/tests/fixtures/workspace/tool/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/tool/src/lib.rs create mode 100644 allow-list/tests/fixtures/workspace/unixonly/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/unixonly/src/lib.rs create mode 100644 allow-list/tests/fixtures/workspace/winonly/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/winonly/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index ff0770f..1bdf775 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,6 +22,9 @@ dependencies = [ "semver", "serde", "serde_json", + "spdx", + "time", + "toml", ] [[package]] @@ -480,6 +483,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + [[package]] name = "smallvec" version = "1.15.0" @@ -616,6 +628,47 @@ dependencies = [ "time-core", ] +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -719,6 +772,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen-rt" version = "0.39.0" diff --git a/allow-list/Cargo.toml b/allow-list/Cargo.toml index 823c460..eb3120c 100644 --- a/allow-list/Cargo.toml +++ b/allow-list/Cargo.toml @@ -14,5 +14,8 @@ cyclonedx-bom = "0.8.0" semver = "1.0" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.83" +spdx = "0.10.8" +time = { version = "0.3.41", features = ["formatting"] } +toml = "0.8" diff --git a/allow-list/licenses/apache2.txt b/allow-list/licenses/apache2.txt new file mode 100644 index 0000000..c2a1061 --- /dev/null +++ b/allow-list/licenses/apache2.txt @@ -0,0 +1,178 @@ +============================== Apache-2.0 ===================================== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/allow-list/src/approval.rs b/allow-list/src/approval.rs new file mode 100644 index 0000000..21d0cf9 --- /dev/null +++ b/allow-list/src/approval.rs @@ -0,0 +1,382 @@ +//! Core: check the inventory against the allow-list configuration +//! +//! The inventory decides what each package is and how it is used; the configuration must +//! approve exactly that. Every violation is collected and reported at once. + +use crate::config::{Config, License, Package as ApprovedPackage, VendorPackage}; +use crate::graph::Role; +use crate::inventory::{Component, DeclaredLicense, Inventory}; +use anyhow::anyhow; +use cargo_metadata::{Package, PackageId}; +use semver::Version; +use spdx::LicenseReq; +use std::collections::{BTreeMap, BTreeSet}; + +/// How a component is approved +#[derive(Debug)] +pub(crate) enum Approval<'c> { + /// A workspace member: our own code + FirstParty, + /// An open-source package whose license was reviewed + ThirdParty(&'c ApprovedPackage), + /// A package the vendor licenses to the customer under its commercial license + Vendor(&'c VendorPackage), + /// A package approved for use at build time only + BuildOnly, +} + +/// A component together with its approval +#[derive(Debug)] +pub(crate) struct Approved<'m, 'c> { + pub(crate) component: Component<'m>, + pub(crate) approval: Approval<'c>, +} + +/// An inventory in which every component is approved for the way it is used +#[derive(Debug)] +pub(crate) struct ValidatedInventory<'m, 'c> { + pub(crate) root: &'m Package, + pub(crate) components: Vec>, + pub(crate) edges: BTreeSet<(&'m PackageId, &'m PackageId)>, +} + +impl ValidatedInventory<'_, '_> { + /// The open-source packages that ship in the product, for the license report: + /// runtime components approved as `third_party`, by name with all their versions + pub(crate) fn shipped_third_party(&self) -> BTreeMap> { + let mut shipped: BTreeMap> = BTreeMap::new(); + for approved in &self.components { + if approved.component.role == Role::Runtime + && matches!(approved.approval, Approval::ThirdParty(_)) + { + let package = approved.component.package; + shipped + .entry(package.name.clone()) + .or_default() + .insert(package.version.clone()); + } + } + shipped + } +} + +/// Approve every component of the inventory, or report every violation +pub(crate) fn validate<'m, 'c>( + inventory: Inventory<'m>, + config: &'c Config, +) -> Result, anyhow::Error> { + let mut violations = BTreeSet::new(); + let mut components = Vec::new(); + for component in inventory.components { + match approve(&component, config) { + Ok(approval) => components.push(Approved { + component, + approval, + }), + Err(violation) => { + violations.insert(format!( + "{} {}: {violation}", + component.package.name, component.package.version + )); + } + } + } + + if !violations.is_empty() { + let violations: Vec = violations.into_iter().collect(); + return Err(anyhow!( + "the allow-list does not approve the product's dependencies:\n {}", + violations.join("\n ") + )); + } + Ok(ValidatedInventory { + root: inventory.root, + components, + edges: inventory.edges, + }) +} + +fn approve<'c>(component: &Component, config: &'c Config) -> Result, String> { + if component.first_party { + return Ok(Approval::FirstParty); + } + let name = component.package.name.as_str(); + let third_party = config.third_party.get(name); + let vendor = config.vendor.get(name); + let build_only = config.build_only.contains(name); + let runtime = component.role == Role::Runtime; + + let approval = match (third_party, vendor, build_only) { + (Some(approved), None, false) => Approval::ThirdParty(approved), + (None, Some(vendor), false) => Approval::Vendor(vendor), + (None, None, true) => Approval::BuildOnly, + (None, None, false) if runtime => { + return Err("ships in the product but is not in `third_party` or `vendor`".to_string()) + } + (None, None, false) => { + return Err( + "used at build time but is not in any list (add it to `build_only`)".to_string(), + ) + } + _ => { + return Err( + "is listed in more than one of `third_party`, `vendor` and `build_only`" + .to_string(), + ) + } + }; + + match approval { + Approval::BuildOnly if runtime => Err( + "is approved only as a build tool (`build_only`) but now ships in the product" + .to_string(), + ), + Approval::ThirdParty(approved) if runtime => { + check_reviewed_license(name, approved, &component.license)?; + Ok(approval) + } + _ => Ok(approval), + } +} + +/// The reviewed licenses must still be part of the declared expression (no stale extras) and +/// must satisfy it (no newly mandatory licenses) +fn check_reviewed_license( + name: &str, + approved: &ApprovedPackage, + declared: &DeclaredLicense, +) -> Result<(), String> { + if approved.id != name { + return Err(format!( + "`third_party` entry is keyed `{name}` but has id `{}`", + approved.id + )); + } + if approved.licenses.is_empty() { + return Err("`third_party` entry has no licenses".to_string()); + } + if approved + .licenses + .iter() + .any(|l| matches!(l, License::Unknown)) + { + return Err("`third_party` entry has an `Unknown` license".to_string()); + } + let expression = match declared { + DeclaredLicense::Valid(expression) => expression, + DeclaredLicense::Missing => { + return Err("declares no SPDX `license`, so the review cannot be checked".to_string()) + } + DeclaredLicense::Invalid(reason) => { + return Err(format!("declares an invalid SPDX `license`: {reason}")) + } + }; + + let reviewed: Vec = approved + .licenses + .iter() + .map(|l| { + spdx::license_id(l.spdx_short()) + .map(LicenseReq::from) + .ok_or_else(|| format!("reviewed license {} is not an SPDX id", l.spdx_short())) + }) + .collect::>()?; + let reviewed_names = || { + reviewed + .iter() + .map(LicenseReq::to_string) + .collect::>() + .join(", ") + }; + + if let Some(stale) = reviewed + .iter() + .find(|r| !expression.requirements().any(|e| &e.req == *r)) + { + return Err(format!( + "reviewed license {stale} is not part of the declared license `{expression}`" + )); + } + if !expression.evaluate(|req| reviewed.contains(req)) { + return Err(format!( + "reviewed licenses ({}) do not satisfy the declared license `{expression}`", + reviewed_names() + )); + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::graph::test_util::{key, path_key}; + use crate::graph::{PackageKey, TargetGraph}; + use crate::inventory::test_util::metadata; + use cargo_metadata::Metadata; + + fn config(json: serde_json::Value) -> Config { + serde_json::from_value(json).unwrap() + } + + fn mit(id: &str) -> serde_json::Value { + serde_json::json!({"id": id, "source": "crates.io", "licenses": [{"MIT": {"copyright": "NotPresent"}}]}) + } + + /// Inventory of an `app` with the given (name, declared license, role) dependencies + fn check(deps: &[(&str, Option<&str>, Role)], config: &Config) -> Result<(), String> { + let app = path_key("app", "1.0.0"); + let keys: Vec<(PackageKey, Option<&str>, Role)> = deps + .iter() + .map(|(name, license, role)| (key(name, "1.0.0"), *license, *role)) + .collect(); + let mut packages: Vec<(PackageKey, Option<&str>)> = + keys.iter().map(|(k, l, _)| (k.clone(), *l)).collect(); + packages.push((app.clone(), None)); + let meta: Metadata = metadata(&packages); + let mut members: BTreeMap = + keys.iter().map(|(k, _, r)| (k.clone(), *r)).collect(); + members.insert(app.clone(), Role::Runtime); + let graph = TargetGraph::new(app, members, BTreeSet::new()).unwrap(); + let inventory = crate::inventory::build(&[graph], &meta, |_| false).unwrap(); + validate(inventory, config) + .map(|_| ()) + .map_err(|e| e.to_string()) + } + + fn empty() -> serde_json::Value { + serde_json::json!({"build_only": [], "vendor": {}, "third_party": {}}) + } + + #[test] + fn approves_each_list_for_its_use() { + let mut json = empty(); + json["third_party"]["serde"] = mit("serde"); + json["third_party"]["regex"] = mit("regex"); + json["vendor"]["sfio-promise"] = serde_json::json!({"url": "https://example.com"}); + json["build_only"] = serde_json::json!(["cc"]); + let config = config(json); + check( + &[ + ("serde", Some("MIT OR Apache-2.0"), Role::Runtime), + ("regex", Some("MIT OR Apache-2.0"), Role::BuildTime), + ("sfio-promise", None, Role::Runtime), + ("cc", Some("MIT OR Apache-2.0"), Role::BuildTime), + ], + &config, + ) + .unwrap(); + } + + #[test] + fn reports_every_violation_at_once() { + let mut json = empty(); + json["build_only"] = serde_json::json!(["cc", "both"]); + json["third_party"]["both"] = mit("both"); + let err = check( + &[ + ("aws-lc-rs", Some("ISC"), Role::Runtime), + ("jobserver", Some("MIT"), Role::BuildTime), + ("cc", Some("MIT"), Role::Runtime), + ("both", Some("MIT"), Role::BuildTime), + ], + &config(json), + ) + .unwrap_err(); + assert!( + err.contains("aws-lc-rs 1.0.0: ships in the product"), + "{err}" + ); + assert!(err.contains("jobserver 1.0.0: used at build time"), "{err}"); + assert!( + err.contains("cc 1.0.0: is approved only as a build tool"), + "{err}" + ); + assert!( + err.contains("both 1.0.0: is listed in more than one"), + "{err}" + ); + } + + #[test] + fn checks_reviewed_licenses_against_the_declared_expression() { + let reviewed = |licenses: serde_json::Value| { + let mut json = empty(); + json["third_party"]["x"] = + serde_json::json!({"id": "x", "source": "crates.io", "licenses": licenses}); + config(json) + }; + let mit = serde_json::json!([{"MIT": {"copyright": "NotPresent"}}]); + let mit_isc = serde_json::json!([{"MIT": {"copyright": "NotPresent"}}, {"ISC": {"copyright": "NotPresent"}}]); + let apache_isc = serde_json::json!(["Apache2", {"ISC": {"copyright": "NotPresent"}}]); + let runtime = |declared: &str, config: &Config| { + check(&[("x", Some(declared), Role::Runtime)], config) + }; + + assert!(runtime("MIT OR Apache-2.0", &reviewed(mit.clone())).is_ok()); + assert!(runtime("MIT/Apache-2.0", &reviewed(mit.clone())).is_ok()); + assert!(runtime("Apache-2.0 AND ISC", &reviewed(apache_isc)).is_ok()); + // newly mandatory license + let err = runtime("MIT AND Apache-2.0", &reviewed(mit.clone())).unwrap_err(); + assert!(err.contains("do not satisfy"), "{err}"); + // stale extra reviewed license + let err = runtime("MIT", &reviewed(mit_isc)).unwrap_err(); + assert!(err.contains("ISC is not part of"), "{err}"); + // exceptions are part of a requirement + assert!(runtime("MIT WITH LLVM-exception", &reviewed(mit.clone())).is_err()); + // no usable declaration + let err = check(&[("x", None, Role::Runtime)], &reviewed(mit.clone())).unwrap_err(); + assert!(err.contains("declares no SPDX"), "{err}"); + // build-time packages are not checked + assert!(check( + &[("x", Some("GPL-3.0-only"), Role::BuildTime)], + &reviewed(mit) + ) + .is_ok()); + } + + #[test] + fn checks_third_party_entry_sanity() { + let mut json = empty(); + json["third_party"]["x"] = serde_json::json!({"id": "y", "source": "crates.io", "licenses": [{"MIT": {"copyright": "NotPresent"}}]}); + assert!(check(&[("x", Some("MIT"), Role::Runtime)], &config(json)) + .unwrap_err() + .contains("keyed")); + let mut json = empty(); + json["third_party"]["x"] = + serde_json::json!({"id": "x", "source": "crates.io", "licenses": []}); + assert!(check(&[("x", Some("MIT"), Role::Runtime)], &config(json)) + .unwrap_err() + .contains("no licenses")); + let mut json = empty(); + json["third_party"]["x"] = + serde_json::json!({"id": "x", "source": "crates.io", "licenses": ["Unknown"]}); + assert!(check(&[("x", Some("MIT"), Role::Runtime)], &config(json)) + .unwrap_err() + .contains("Unknown")); + } + + #[test] + fn license_report_lists_only_shipped_third_party_packages() { + let app = path_key("app", "1.0.0"); + let (serde, regex) = (key("serde", "1.0.0"), key("regex", "1.0.0")); + let meta = metadata(&[ + (app.clone(), None), + (serde.clone(), Some("MIT")), + (regex.clone(), Some("MIT")), + ]); + let members = BTreeMap::from([ + (app.clone(), Role::Runtime), + (serde, Role::Runtime), + (regex, Role::BuildTime), + ]); + let graph = TargetGraph::new(app, members, BTreeSet::new()).unwrap(); + let inventory = crate::inventory::build(&[graph], &meta, |_| false).unwrap(); + let mut json = empty(); + json["third_party"]["serde"] = mit("serde"); + json["third_party"]["regex"] = mit("regex"); + let config = config(json); + let validated = validate(inventory, &config).unwrap(); + let shipped: Vec = validated.shipped_third_party().into_keys().collect(); + assert_eq!(shipped, ["serde"]); + } +} diff --git a/allow-list/src/cli.rs b/allow-list/src/cli.rs index 6d8e620..ea0d80b 100644 --- a/allow-list/src/cli.rs +++ b/allow-list/src/cli.rs @@ -1,4 +1,6 @@ -use clap::{Parser, Subcommand}; +use crate::commands::{target_dirs, Evidence, SbomOptions}; +use crate::input::TargetInput; +use clap::{Args, Parser, Subcommand}; use std::path::PathBuf; #[derive(Parser)] @@ -9,9 +11,12 @@ pub(crate) struct Cli { pub(crate) command: Commands, } +// variant names are the CLI subcommand names, so they keep their common `Gen` prefix +#[allow(clippy::enum_variant_names)] #[derive(Subcommand)] pub(crate) enum Commands { /// outputs a human-readable report of all 3rd party licenses + /// (deprecated: reads a cargo-cyclonedx SBOM, which does not reflect the features actually built) GenLicenses { /// path to the cyclonedx JSON #[clap(value_parser, long, short = 'b')] @@ -21,6 +26,7 @@ pub(crate) enum Commands { config_path: PathBuf, }, /// outputs a human-readable report of all 3rd party licenses + /// (deprecated: reads cargo-cyclonedx SBOMs, which do not reflect the features actually built) GenLicensesDir { /// list all the directories in this directory #[clap(value_parser, long, short = 'l')] @@ -32,33 +38,124 @@ pub(crate) enum Commands { #[clap(value_parser, long, short = 'c')] config_path: PathBuf, }, - /// outputs a human-readable report of all 3rd party licenses from a cargo - /// build log (`cargo build --message-format=json`), scoped to what actually compiled + /// outputs a human-readable report of the 3rd party licenses that ship in the product, + /// from the build evidence of one target GenLicensesLog { - /// path to the cargo build log (JSON message stream) - #[clap(value_parser, long, short = 'g')] - log_path: PathBuf, - /// path to `cargo metadata --format-version 1` JSON output - #[clap(value_parser, long, short = 'm')] - metadata_path: PathBuf, - /// path to the JSON configuration (allow-list) - #[clap(value_parser, long, short = 'c')] - config_path: PathBuf, + #[clap(flatten)] + target: TargetFiles, + #[clap(flatten)] + common: Common, }, - /// outputs a human-readable report of all 3rd party licenses from cargo - /// build logs in subdirectories, scoped to what actually compiled + /// outputs a human-readable report of the 3rd party licenses that ship in the product, + /// from the build evidence of every target in the subdirectories of a directory GenLicensesLogDir { - /// list all the directories in this directory - #[clap(value_parser, long, short = 'l')] - list_dir: PathBuf, - /// name of the build log file in each directory - #[clap(value_parser, long, short = 'g')] - log_file: String, - /// path to `cargo metadata --format-version 1` JSON output - #[clap(value_parser, long, short = 'm')] - metadata_path: PathBuf, - /// path to the JSON configuration (allow-list) - #[clap(value_parser, long, short = 'c')] - config_path: PathBuf, + #[clap(flatten)] + targets: TargetDir, + #[clap(flatten)] + common: Common, + }, + /// outputs a CycloneDX 1.5 JSON SBOM of the product, from the build evidence of one target + GenSbomLog { + #[clap(flatten)] + target: TargetFiles, + #[clap(flatten)] + common: Common, + #[clap(flatten)] + sbom: SbomArgs, + }, + /// outputs a CycloneDX 1.5 JSON SBOM of the product, from the build evidence of every + /// target in the subdirectories of a directory + GenSbomLogDir { + #[clap(flatten)] + targets: TargetDir, + #[clap(flatten)] + common: Common, + #[clap(flatten)] + sbom: SbomArgs, }, } + +/// Options of the SBOM commands +#[derive(Args)] +pub(crate) struct SbomArgs { + /// path to the `Cargo.lock`, to add SHA-256 hashes of crates.io packages + #[clap(value_parser, long)] + lockfile: Option, + /// omit the random serial number, for reproducible output (with `SOURCE_DATE_EPOCH`) + #[clap(long)] + omit_serial_number: bool, +} + +impl From for SbomOptions { + fn from(args: SbomArgs) -> Self { + Self { + lockfile: args.lockfile, + omit_serial_number: args.omit_serial_number, + } + } +} + +/// The build evidence of one target +#[derive(Args)] +pub(crate) struct TargetFiles { + /// path to the `cargo build --message-format json` log + #[clap(value_parser, long, short = 'g')] + log_path: PathBuf, + /// path to the `cargo tree -e normal,build --prefix depth --format '{p}|{f}'` output + #[clap(value_parser, long)] + tree_path: PathBuf, + /// path to the `cargo tree -e normal,no-proc-macro --prefix depth --format '{p}|{f}'` output + #[clap(value_parser, long)] + runtime_tree_path: PathBuf, +} + +/// The build evidence of several targets +#[derive(Args)] +pub(crate) struct TargetDir { + /// directory with one subdirectory per target, each containing `build.json`, `tree.txt` + /// and `runtime-tree.txt` + #[clap(value_parser, long, short = 'l')] + list_dir: PathBuf, +} + +/// Arguments shared by every command that reads build evidence +#[derive(Args)] +pub(crate) struct Common { + /// name of the workspace package that is the product (e.g. `dnp3-ffi`) + #[clap(long)] + root_package: String, + /// path to `cargo metadata --format-version 1 --all-features` JSON output + #[clap(value_parser, long, short = 'm')] + metadata_path: PathBuf, + /// path to the JSON configuration (allow-list) + #[clap(value_parser, long, short = 'c')] + config_path: PathBuf, +} + +impl TargetFiles { + pub(crate) fn evidence(self, common: Common) -> Evidence { + let target = TargetInput::LogAndTree { + log: self.log_path, + tree: self.tree_path, + runtime_tree: self.runtime_tree_path, + }; + common.evidence(vec![target]) + } +} + +impl TargetDir { + pub(crate) fn evidence(self, common: Common) -> Result { + Ok(common.evidence(target_dirs(&self.list_dir)?)) + } +} + +impl Common { + fn evidence(self, targets: Vec) -> Evidence { + Evidence { + targets, + root_package: self.root_package, + metadata: self.metadata_path, + config: self.config_path, + } + } +} diff --git a/allow-list/src/commands.rs b/allow-list/src/commands.rs new file mode 100644 index 0000000..7e55b57 --- /dev/null +++ b/allow-list/src/commands.rs @@ -0,0 +1,128 @@ +//! Command glue: load the evidence once, run the core, render an output + +use crate::approval::{self, ValidatedInventory}; +use crate::config::Config; +use crate::input::TargetInput; +use crate::sbom::{self, Checksums}; +use crate::{inventory, licenses}; +use anyhow::{anyhow, Context}; +use cargo_metadata::Metadata; +use cyclonedx_bom::prelude::DateTime; +use serde::de::DeserializeOwned; +use std::fs::{read_dir, File}; +use std::io::{BufReader, Write}; +use std::path::{Path, PathBuf}; +use time::format_description::well_known::Rfc3339; +use time::OffsetDateTime; + +/// Everything needed to describe one product build +pub(crate) struct Evidence { + /// One entry per target the product is built for + pub(crate) targets: Vec, + /// Name of the workspace package that is the product + pub(crate) root_package: String, + /// `cargo metadata --format-version 1 --all-features` output + pub(crate) metadata: PathBuf, + /// The allow-list configuration + pub(crate) config: PathBuf, +} + +/// One target per immediate subdirectory of `dir`, in sorted order +pub(crate) fn target_dirs(dir: &Path) -> Result, anyhow::Error> { + let mut dirs = Vec::new(); + for entry in read_dir(dir).with_context(|| format!("listing {}", dir.display()))? { + let path = entry?.path(); + if path.is_dir() { + dirs.push(path); + } + } + if dirs.is_empty() { + return Err(anyhow!("{} has no target subdirectories", dir.display())); + } + dirs.sort(); + Ok(dirs.iter().map(|d| TargetInput::from_dir(d)).collect()) +} + +/// Write the human-readable report of the open-source licenses that ship in the product +pub(crate) fn gen_licenses(evidence: &Evidence, w: W) -> Result<(), anyhow::Error> { + let config: Config = load_json(&evidence.config)?; + let metadata: Metadata = load_json(&evidence.metadata)?; + let validated = validate(evidence, &metadata, &config)?; + licenses::gen_licenses_for(&validated.shipped_third_party(), &config, w) +} + +/// Options of the SBOM commands +pub(crate) struct SbomOptions { + /// `Cargo.lock` from which to take SHA-256 hashes of crates.io packages + pub(crate) lockfile: Option, + /// Omit the random serial number, for reproducible output + pub(crate) omit_serial_number: bool, +} + +/// Write a CycloneDX SBOM of the product +pub(crate) fn gen_sbom( + evidence: &Evidence, + options: &SbomOptions, + w: W, +) -> Result<(), anyhow::Error> { + let config: Config = load_json(&evidence.config)?; + let metadata: Metadata = load_json(&evidence.metadata)?; + let validated = validate(evidence, &metadata, &config)?; + let checksums = match &options.lockfile { + Some(path) => Some( + Checksums::from_lockfile(&std::fs::read_to_string(path)?) + .with_context(|| format!("parsing {}", path.display()))?, + ), + None => None, + }; + let options = sbom::Options { + checksums: checksums.as_ref(), + omit_serial_number: options.omit_serial_number, + timestamp: timestamp()?, + }; + sbom::write(&validated, config.commercial_license.as_ref(), &options, w) +} + +/// `SOURCE_DATE_EPOCH` (for reproducible builds) if set, otherwise now +fn timestamp() -> Result { + match std::env::var("SOURCE_DATE_EPOCH") { + Ok(epoch) => { + let epoch: i64 = epoch + .trim() + .parse() + .with_context(|| format!("invalid SOURCE_DATE_EPOCH {epoch:?}"))?; + let time = OffsetDateTime::from_unix_timestamp(epoch)?.format(&Rfc3339)?; + Ok(DateTime::try_from(time)?) + } + Err(std::env::VarError::NotPresent) => Ok(DateTime::now()?), + Err(err) => Err(anyhow!("invalid SOURCE_DATE_EPOCH: {err}")), + } +} + +/// Read every target's evidence and validate the product's inventory against the configuration +pub(crate) fn validate<'m, 'c>( + evidence: &Evidence, + metadata: &'m Metadata, + config: &'c Config, +) -> Result, anyhow::Error> { + let graphs = evidence + .targets + .iter() + .map(|target| { + target + .read(&evidence.root_package) + .with_context(|| format!("reading build evidence: {target}")) + }) + .collect::, _>>()?; + let inventory = inventory::build(&graphs, metadata, |name| config.is_embedded(name))?; + approval::validate(inventory, config) +} + +/// Load a JSON file: the allow-list configuration, or the `cargo metadata --format-version 1` +/// output (which is only a dictionary of package details: license, source, workspace +/// membership; it never determines scope or roles) +fn load_json(path: &Path) -> Result { + let file = File::open(path).with_context(|| format!("opening {}", path.display()))?; + serde_json::from_reader(BufReader::new(file)) + .with_context(|| format!("parsing {}", path.display())) +} diff --git a/allow-list/src/config.rs b/allow-list/src/config.rs index b440ad8..4132750 100644 --- a/allow-list/src/config.rs +++ b/allow-list/src/config.rs @@ -65,6 +65,9 @@ pub(crate) enum License { /// Unicode License Agreement - Data Files and Software (2016) #[serde(rename = "UnicodeDFS2016")] UnicodeDfs2016, + /// Apache License 2.0 - + #[serde(rename = "Apache2")] + Apache2, } /// Information about a dependency @@ -76,6 +79,10 @@ pub(crate) struct Package { pub(crate) source: Source, /// license identification pub(crate) licenses: Vec, + /// set when a build-time dependency copies its own code into the product (e.g. a build + /// script writes source it provides), so it ships even though it is not linked + #[serde(default)] + pub(crate) embedded: bool, } impl Package { @@ -91,6 +98,18 @@ impl Package { pub(crate) struct VendorPackage { /// SCM URL where the package is located pub(crate) url: String, + /// see [`Package::embedded`] + #[serde(default)] + pub(crate) embedded: bool, +} + +/// The commercial license under which the vendor licenses its own code to the customer +#[derive(Serialize, Deserialize, Debug)] +pub(crate) struct CommercialLicense { + /// Human readable name of the license + pub(crate) name: String, + /// URL of the license text + pub(crate) url: String, } /// Represent a configuration file for a particular project @@ -102,6 +121,17 @@ pub(crate) struct Config { pub(crate) vendor: BTreeMap, /// 3rd party packages that are allowed to be build dependencies pub(crate) third_party: BTreeMap, + /// license of first-party and vendor packages, required to generate an SBOM + #[serde(default)] + pub(crate) commercial_license: Option, +} + +impl Config { + /// Whether the package is marked as shipping its code although it is a build-time dependency + pub(crate) fn is_embedded(&self, name: &str) -> bool { + self.third_party.get(name).is_some_and(|p| p.embedded) + || self.vendor.get(name).is_some_and(|p| p.embedded) + } } impl License { @@ -124,6 +154,7 @@ impl License { License::Mpl2 => None, License::Bsd3 { copyright } => Some(copyright.lines()), License::UnicodeDfs2016 => None, + License::Apache2 => None, } } @@ -139,6 +170,7 @@ impl License { License::UnicodeDfs2016 => { std::include_str!("../licenses/unicode_dfs_2016.txt") } + License::Apache2 => std::include_str!("../licenses/apache2.txt"), License::Unknown => panic!("You must define unknown licenses"), } } @@ -153,6 +185,7 @@ impl License { License::Mpl2 => "MPL-2.0", License::Bsd3 { .. } => "BSD-3-Clause", License::UnicodeDfs2016 => "Unicode-DFS-2016", + License::Apache2 => "Apache-2.0", License::Unknown => { panic!("You must define unknown licenses") } @@ -169,6 +202,7 @@ impl License { License::Mpl2 => "https://spdx.org/licenses/MPL-2.0.html", License::Bsd3 { .. } => "https://spdx.org/licenses/BSD-3-Clause.html", License::UnicodeDfs2016 => "https://spdx.org/licenses/Unicode-DFS-2016.html", + License::Apache2 => "https://spdx.org/licenses/Apache-2.0.html", License::Unknown => { panic!("You must define unknown licenses") } diff --git a/allow-list/src/fixture_tests.rs b/allow-list/src/fixture_tests.rs new file mode 100644 index 0000000..1eb7882 --- /dev/null +++ b/allow-list/src/fixture_tests.rs @@ -0,0 +1,255 @@ +//! End-to-end tests that run the installed Cargo on the fixture workspace in +//! `tests/fixtures/workspace`, then read the evidence with the real reader and core. +//! +//! These pin down the contract with Cargo itself (tree grammar, classification by `cargo tree`, +//! artifact features) and fail when a new Cargo release changes it. + +use crate::config::Config; +use crate::graph::{PackageKey, Role, TargetGraph}; +use crate::input::TargetInput; +use crate::{approval, inventory}; +use cargo_metadata::Metadata; +use std::collections::{BTreeMap, BTreeSet}; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::sync::OnceLock; + +/// The fixture's build evidence, produced once per test run with the README recipe +struct Evidence { + dir: PathBuf, + metadata: Metadata, +} + +fn evidence() -> &'static Evidence { + static EVIDENCE: OnceLock = OnceLock::new(); + EVIDENCE.get_or_init(|| { + let workspace = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/workspace"); + let dir = std::env::temp_dir().join(format!("allow-list-fixture-{}", std::process::id())); + std::fs::create_dir_all(&dir).unwrap(); + let host = host_triple(); + let args = ["-p", "app", "--target", &host, "--locked", "--offline"]; + let tree_format = [ + "--prefix", "depth", "--color", "never", "--format", "{p}|{f}", + ]; + + let target_dir = dir.join("target"); + let target_dir = target_dir.to_str().unwrap(); + cargo( + &workspace, + &dir.join("build.json"), + &[ + &[ + "build", + "--message-format", + "json", + "--target-dir", + target_dir, + ][..], + &args[..], + ] + .concat(), + ); + cargo( + &workspace, + &dir.join("tree.txt"), + &[ + &["tree", "-e", "normal,build"][..], + &args[..], + &tree_format[..], + ] + .concat(), + ); + cargo( + &workspace, + &dir.join("runtime-tree.txt"), + &[ + &["tree", "-e", "normal,no-proc-macro"][..], + &args[..], + &tree_format[..], + ] + .concat(), + ); + cargo( + &workspace, + &dir.join("metadata.json"), + &[ + "metadata", + "--format-version", + "1", + "--all-features", + "--locked", + "--offline", + ], + ); + let metadata = + serde_json::from_slice(&std::fs::read(dir.join("metadata.json")).unwrap()).unwrap(); + Evidence { dir, metadata } + }) +} + +fn host_triple() -> String { + let output = Command::new(cargo_bin()).arg("-vV").output().unwrap(); + String::from_utf8(output.stdout) + .unwrap() + .lines() + .find_map(|l| l.strip_prefix("host: ").map(str::to_string)) + .unwrap() +} + +fn cargo_bin() -> String { + std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()) +} + +/// Run cargo in `dir`, writing its stdout to `out` +fn cargo(dir: &Path, out: &Path, args: &[&str]) { + let output = Command::new(cargo_bin()) + .current_dir(dir) + .args(args) + .output() + .unwrap(); + assert!( + output.status.success(), + "cargo {args:?} failed: {}", + String::from_utf8_lossy(&output.stderr) + ); + std::fs::write(out, output.stdout).unwrap(); +} + +fn input(log: &Path) -> TargetInput { + let dir = &evidence().dir; + TargetInput::LogAndTree { + log: log.to_path_buf(), + tree: dir.join("tree.txt"), + runtime_tree: dir.join("runtime-tree.txt"), + } +} + +fn read() -> TargetGraph { + input(&evidence().dir.join("build.json")) + .read("app") + .unwrap() +} + +fn roles(graph: &TargetGraph) -> BTreeMap<&str, Role> { + graph + .packages() + .iter() + .map(|(key, role)| (key.name.as_str(), *role)) + .collect() +} + +fn edges(graph: &TargetGraph) -> BTreeSet<(&str, &str)> { + graph + .edges() + .iter() + .map(|(from, to)| (from.name.as_str(), to.name.as_str())) + .collect() +} + +#[test] +fn cargo_classifies_runtime_and_build_time_packages() { + let graph = read(); + let expected = BTreeMap::from([ + ("app", Role::Runtime), + // renamed optional dependency with a custom lib name, activated through `dep:` + ("alias-target", Role::Runtime), + // a runtime dependency also used (with the same features) by a build dependency + ("common", Role::Runtime), + // a runtime dependency also used (with different features) beneath a proc-macro + ("shared", Role::Runtime), + ("unixonly", Role::Runtime), + ("pm", Role::BuildTime), + ("pmonly", Role::BuildTime), + ("tool", Role::BuildTime), + ]); + let expected: BTreeMap<&str, Role> = expected + .into_iter() + .filter(|(name, _)| cfg!(unix) || *name != "unixonly") + .collect(); + // `optdep` (disabled feature) and `winonly`/`unixonly` (other platform) never compile + assert_eq!(roles(&graph), expected); +} + +#[test] +fn cargo_tree_edges_include_every_expansion() { + let graph = read(); + let mut expected = BTreeSet::from([ + ("app", "alias-target"), + ("app", "common"), + ("app", "pm"), + ("app", "shared"), + ("app", "tool"), + ("pm", "pmonly"), + ("pm", "shared"), + ("tool", "common"), + ]); + if cfg!(unix) { + expected.insert(("app", "unixonly")); + } + assert_eq!(edges(&graph), expected); +} + +/// Copy the build log without the first artifact line of `package` that `select` accepts +fn log_without(package: &str, select: impl Fn(&serde_json::Value) -> bool) -> PathBuf { + let dir = &evidence().dir; + let text = std::fs::read_to_string(dir.join("build.json")).unwrap(); + let mut removed = false; + let lines: Vec<&str> = text + .lines() + .filter(|line| { + let message: serde_json::Value = serde_json::from_str(line).unwrap_or_default(); + let is_target = message["reason"] == "compiler-artifact" + && message["package_id"] + .as_str() + .unwrap_or("") + .contains(&format!("/{package}#")) + && message["target"]["kind"][0] != "custom-build" + && select(&message); + let drop = is_target && !removed; + removed |= drop; + !drop + }) + .collect(); + assert!(removed, "no artifact of {package} to remove"); + let path = dir.join(format!("build-without-{package}.json")); + std::fs::write(&path, lines.join("\n")).unwrap(); + path +} + +#[test] +fn a_dropped_artifact_with_distinct_features_is_detected() { + let log = log_without("shared", |m| m["features"][0] == "host-feat"); + let err = input(&log).read("app").unwrap_err(); + assert!( + format!("{err:#}").contains("shared@0.1.0 (path) [host-feat]"), + "{err:#}" + ); +} + +#[test] +fn a_dropped_artifact_with_identical_features_is_not_detected() { + // Documented limit: `common` compiles twice (host and target) with identical features, so + // the variant sets cannot tell that one of the artifacts is missing. + let log = log_without("common", |_| true); + assert!(input(&log).read("app").is_ok()); +} + +#[test] +fn the_core_needs_no_approval_for_workspace_members() { + let graph = read(); + let inventory = inventory::build(&[graph], &evidence().metadata, |_| false).unwrap(); + assert!(inventory.components.iter().all(|c| c.first_party)); + let config: Config = + serde_json::from_str(r#"{"build_only": [], "vendor": {}, "third_party": {}}"#).unwrap(); + let validated = approval::validate(inventory, &config).unwrap(); + assert!(validated.shipped_third_party().is_empty()); +} + +#[test] +fn keys_resolve_to_workspace_members() { + let graph = read(); + let keys: Vec<&PackageKey> = graph.packages().keys().collect(); + assert!(keys + .iter() + .all(|k| k.source == crate::graph::SourceKind::Path)); +} diff --git a/allow-list/src/golden_tests.rs b/allow-list/src/golden_tests.rs new file mode 100644 index 0000000..ac856fd --- /dev/null +++ b/allow-list/src/golden_tests.rs @@ -0,0 +1,426 @@ +//! Golden tests on real build evidence of dnp3 1.7.0 (`tests/fixtures/dnp3`): the `dnp3-ffi` +//! library built for `x86_64-unknown-linux-gnu` with `serial,tls-aws-lc` (`targets/aws`) and +//! with `serial,tls` (`targets/ring`). Paths are sanitized and the metadata is trimmed. +//! +//! The expected roles of the `aws` target were derived independently from Cargo's nightly SBOM +//! precursor file for the same build (`normal`-edge reachability from the root). + +use crate::commands::{self, target_dirs, Evidence, SbomOptions}; +use crate::config::Config; +use crate::graph::Role; +use crate::input::TargetInput; +use crate::sbom::{self, Checksums}; +use cargo_metadata::Metadata; +use cyclonedx_bom::prelude::*; +use std::collections::{BTreeMap, BTreeSet}; +use std::path::{Path, PathBuf}; + +const RUNTIME: [&str; 88] = [ + "aes", + "aws-lc-rs", + "aws-lc-sys", + "base64", + "base64ct", + "bitflags", + "block-buffer", + "block-padding", + "bytes", + "cbc", + "cfg-if", + "chrono", + "cipher", + "const-oid", + "cpufeatures", + "crypto-common", + "der", + "digest", + "dnp3", + "dnp3-ffi", + "futures", + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", + "generic-array", + "hmac", + "iana-time-zone", + "inout", + "itoa", + "lazy_static", + "libc", + "log", + "memchr", + "mio", + "mio-serial", + "nix", + "nu-ansi-term", + "num-traits", + "num_cpus", + "once_cell", + "pbkdf2", + "pem", + "pem-rfc7468", + "pin-project-lite", + "pkcs5", + "pkcs8", + "rand_core", + "rustls", + "rustls-pki-types", + "rustls-webpki", + "rx509", + "salsa20", + "scopeguard", + "scrypt", + "scursor", + "serde", + "serde_core", + "serde_json", + "serialport", + "sfio-promise", + "sfio-rustls-config", + "sha2", + "sharded-slab", + "slab", + "smallvec", + "socket2", + "spki", + "subtle", + "thiserror", + "thread_local", + "tokio", + "tokio-rustls", + "tokio-serial", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", + "tracing-subscriber", + "typenum", + "unescaper", + "untrusted", + "xxhash-rust", + "zeroize", + "zmij", +]; + +const BUILD_TIME: [&str; 50] = [ + "addr2line", + "adler2", + "aho-corasick", + "anstream", + "anstyle", + "anstyle-parse", + "anstyle-query", + "autocfg", + "backtrace", + "cc", + "cfg_aliases", + "clap", + "clap_builder", + "clap_derive", + "clap_lex", + "cmake", + "colorchoice", + "dnp3-schema", + "dunce", + "find-msvc-tools", + "fs_extra", + "futures-macro", + "gimli", + "heck", + "is_terminal_polyfill", + "jobserver", + "miniz_oxide", + "object", + "oo-bindgen", + "pkg-config", + "platforms", + "proc-macro2", + "quote", + "regex", + "regex-automata", + "regex-syntax", + "rustc-demangle", + "semver", + "serde_derive", + "sfio-tokio-ffi", + "sfio-tracing-ffi", + "shlex", + "strsim", + "syn", + "thiserror-impl", + "tokio-macros", + "tracing-attributes", + "unicode-ident", + "utf8parse", + "version_check", +]; + +/// Build-time dependencies whose code ships, marked `embedded` in the fixture's config +const EMBEDDED: [&str; 3] = ["oo-bindgen", "sfio-tokio-ffi", "sfio-tracing-ffi"]; + +fn fixture(path: &str) -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")) + .join("tests/fixtures/dnp3") + .join(path) +} + +fn evidence(targets: Vec) -> Evidence { + Evidence { + targets, + root_package: "dnp3-ffi".to_string(), + metadata: fixture("metadata.json"), + config: fixture("allowed.json"), + } +} + +fn all_targets() -> Evidence { + evidence(target_dirs(&fixture("targets")).unwrap()) +} + +fn one_target(name: &str) -> Evidence { + evidence(vec![TargetInput::from_dir(&fixture("targets").join(name))]) +} + +fn load(path: &str) -> T { + serde_json::from_slice(&std::fs::read(fixture(path)).unwrap()).unwrap() +} + +/// (name, role) of every component of a validated inventory, plus the root +fn roles(evidence: &Evidence, config: &Config) -> BTreeMap { + let metadata: Metadata = load("metadata.json"); + let validated = commands::validate(evidence, &metadata, config).unwrap(); + let mut roles: BTreeMap = validated + .components + .iter() + .map(|a| (a.component.package.name.clone(), a.component.role)) + .collect(); + roles.insert(validated.root.name.clone(), Role::Runtime); + roles +} + +#[test] +fn reader_classifies_the_aws_build_like_cargos_sbom_precursor() { + let graph = TargetInput::from_dir(&fixture("targets/aws")) + .read("dnp3-ffi") + .unwrap(); + let names = |role| -> BTreeSet<&str> { + graph + .packages() + .iter() + .filter(|(_, r)| **r == role) + .map(|(k, _)| k.name.as_str()) + .collect() + }; + assert_eq!(names(Role::Runtime), BTreeSet::from(RUNTIME)); + assert_eq!(names(Role::BuildTime), BTreeSet::from(BUILD_TIME)); +} + +#[test] +fn embedded_build_dependencies_ship_and_their_dependencies_do_not() { + let config: Config = load("allowed.json"); + let roles = roles(&one_target("aws"), &config); + for name in EMBEDDED { + assert_eq!(roles[name], Role::Runtime, "{name}"); + } + // oo-bindgen's own dependencies stay build-time + assert_eq!(roles["regex"], Role::BuildTime); + assert_eq!(roles["heck"], Role::BuildTime); +} + +#[test] +fn each_target_contains_only_its_tls_provider_and_the_merge_contains_both() { + let config: Config = load("allowed.json"); + let aws = roles(&one_target("aws"), &config); + let ring = roles(&one_target("ring"), &config); + let merged = roles(&all_targets(), &config); + assert!(aws.contains_key("aws-lc-sys") && !aws.contains_key("ring")); + assert!(ring.contains_key("ring") && !ring.contains_key("aws-lc-sys")); + assert_eq!(merged["ring"], Role::Runtime); + assert_eq!(merged["aws-lc-sys"], Role::Runtime); +} + +#[test] +fn unapproved_or_misreviewed_dependencies_are_all_reported() { + let mut config: Config = load("allowed.json"); + config.third_party.remove("aws-lc-sys"); + config.build_only.remove("jobserver"); + config.build_only.insert("tokio".to_string()); + config.third_party.remove("tokio"); + config + .third_party + .get_mut("ring") + .unwrap() + .licenses + .remove(0); + let metadata: Metadata = load("metadata.json"); + let err = commands::validate(&all_targets(), &metadata, &config) + .unwrap_err() + .to_string(); + for expected in [ + "aws-lc-sys 0.45.0: ships in the product but is not in `third_party` or `vendor`", + "jobserver 0.1.34: used at build time but is not in any list", + "tokio 1.52.1: is approved only as a build tool", + "ring 0.17.14: reviewed licenses (ISC) do not satisfy", + ] { + assert!(err.contains(expected), "missing {expected:?} in:\n{err}"); + } +} + +#[test] +fn license_report_lists_exactly_the_shipped_third_party_crates() { + let mut out = Vec::new(); + commands::gen_licenses(&all_targets(), &mut out).unwrap(); + let report = String::from_utf8(out).unwrap(); + let crates: BTreeSet<&str> = report + .lines() + .filter_map(|l| l.strip_prefix("crate: ")) + .collect(); + assert!( + crates.contains("ring") && crates.contains("aws-lc-sys") && crates.contains("oo-bindgen") + ); + for build_time in ["syn", "serde_derive", "regex", "cc", "tokio-macros"] { + assert!(!crates.contains(build_time), "{build_time}"); + } + for not_third_party in ["dnp3", "sfio-promise", "sfio-tokio-ffi"] { + assert!(!crates.contains(not_third_party), "{not_third_party}"); + } + assert_eq!(crates, sbom_required_third_party(&sbom_document())); +} + +/// The SBOM of all targets, with a fixed timestamp and no serial number +fn sbom_bytes() -> Vec { + let config: Config = load("allowed.json"); + let metadata: Metadata = load("metadata.json"); + let validated = commands::validate(&all_targets(), &metadata, &config).unwrap(); + let checksums = + Checksums::from_lockfile(&std::fs::read_to_string(fixture("Cargo.lock")).unwrap()).unwrap(); + let options = sbom::Options { + checksums: Some(&checksums), + omit_serial_number: true, + timestamp: DateTime::try_from("2025-10-09T08:53:20Z".to_string()).unwrap(), + }; + let mut out = Vec::new(); + sbom::write( + &validated, + config.commercial_license.as_ref(), + &options, + &mut out, + ) + .unwrap(); + out +} + +fn sbom_document() -> serde_json::Value { + serde_json::from_slice(&sbom_bytes()).unwrap() +} + +/// Names of the `required` components whose license is an SPDX expression (third-party code) +fn sbom_required_third_party(bom: &serde_json::Value) -> BTreeSet<&str> { + let config: Config = load("allowed.json"); + bom["components"] + .as_array() + .unwrap() + .iter() + .filter(|c| c["scope"] == "required") + .map(|c| c["name"].as_str().unwrap()) + .filter(|name| config.third_party.contains_key(*name)) + .collect() +} + +#[test] +fn sbom_is_valid_cyclonedx_1_5() { + let bom = Bom::parse_from_json_v1_5(sbom_bytes().as_slice()).unwrap(); + let validation = bom.validate_version(SpecVersion::V1_5); + assert!(validation.passed(), "{validation:?}"); +} + +#[test] +fn sbom_scopes_licenses_hashes_and_edges() { + let bom = sbom_document(); + let components = bom["components"].as_array().unwrap(); + let component = |name: &str| components.iter().find(|c| c["name"] == name).unwrap(); + + assert_eq!(bom["metadata"]["component"]["name"], "dnp3-ffi"); + assert!(bom.get("serialNumber").is_none()); + assert_eq!(component("ring")["scope"], "required"); + assert_eq!(component("aws-lc-sys")["scope"], "required"); + assert_eq!(component("serde_derive")["scope"], "excluded"); + assert_eq!(component("sfio-tokio-ffi")["scope"], "required"); + assert_eq!( + component("ring")["licenses"][0]["expression"], + "Apache-2.0 AND ISC" + ); + // legacy `/` syntax is normalized + assert_eq!( + component("unescaper")["licenses"][0]["expression"], + "GPL-3.0 OR MIT" + ); + assert_eq!( + component("dnp3")["licenses"][0]["license"]["name"], + "Step Function I/O License Agreement" + ); + assert_eq!( + component("sfio-promise")["externalReferences"][0]["type"], + "vcs" + ); + assert!(component("dnp3").get("hashes").is_none()); + + let lock = std::fs::read_to_string(fixture("Cargo.lock")).unwrap(); + let serde_hash = component("serde")["hashes"][0]["content"].as_str().unwrap(); + assert!(lock.contains(&format!("checksum = \"{serde_hash}\""))); + assert_eq!(component("serde")["hashes"][0]["alg"], "SHA-256"); + + let depends_on = |from: &str, to: &str| { + let from = format!("pkg:cargo/{from}@"); + let to = format!("pkg:cargo/{to}@"); + bom["dependencies"].as_array().unwrap().iter().any(|d| { + d["ref"].as_str().unwrap().starts_with(&from) + && d["dependsOn"] + .as_array() + .unwrap() + .iter() + .any(|t| t.as_str().unwrap().starts_with(&to)) + }) + }; + assert!(depends_on("dnp3-ffi", "dnp3")); + assert!(depends_on("dnp3", "tokio")); + assert!(depends_on("aws-lc-rs", "aws-lc-sys")); + assert!(depends_on("dnp3-ffi", "oo-bindgen")); + assert!(!depends_on("dnp3", "dnp3")); +} + +#[test] +fn sbom_is_reproducible() { + assert_eq!(sbom_bytes(), sbom_bytes()); +} + +#[test] +fn sbom_needs_a_commercial_license_and_lockfile_checksums() { + let mut out = Vec::new(); + let mut evidence = all_targets(); + let mut config: serde_json::Value = load("allowed.json"); + config.as_object_mut().unwrap().remove("commercial_license"); + let dir = std::env::temp_dir().join(format!("allow-list-golden-{}", std::process::id())); + std::fs::create_dir_all(&dir).unwrap(); + evidence.config = dir.join("allowed.json"); + std::fs::write(&evidence.config, config.to_string()).unwrap(); + let options = SbomOptions { + lockfile: None, + omit_serial_number: false, + }; + let err = commands::gen_sbom(&evidence, &options, &mut out).unwrap_err(); + assert!(err.to_string().contains("commercial_license"), "{err}"); + + let lock = dir.join("Cargo.lock"); + std::fs::write(&lock, "version = 4\n").unwrap(); + let options = SbomOptions { + lockfile: Some(lock), + omit_serial_number: false, + }; + let err = commands::gen_sbom(&all_targets(), &options, &mut out).unwrap_err(); + assert!(err.to_string().contains("no checksum"), "{err}"); +} diff --git a/allow-list/src/graph.rs b/allow-list/src/graph.rs new file mode 100644 index 0000000..0dd3d9d --- /dev/null +++ b/allow-list/src/graph.rs @@ -0,0 +1,166 @@ +//! The format-neutral contract between input readers and the core. +//! +//! An input reader turns one target's raw build evidence into a [`TargetGraph`]. Nothing after +//! a reader knows any input format, so new readers (e.g. Cargo's SBOM precursor files) can be +//! added without touching the core. + +use anyhow::anyhow; +use semver::Version; +use std::collections::{BTreeMap, BTreeSet}; +use std::fmt; + +/// Source ids under which Cargo refers to crates.io +const CRATES_IO_SOURCES: [&str; 2] = [ + "registry+https://github.com/rust-lang/crates.io-index", + "sparse+https://index.crates.io/", +]; + +/// Whether a Cargo source id (as in package ids and `cargo metadata`) refers to crates.io +pub(crate) fn is_crates_io(source: &str) -> bool { + CRATES_IO_SOURCES.contains(&source) +} + +/// Where a package came from, as every reader can state it +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) enum SourceKind { + /// The crates.io registry + CratesIo, + /// A local path (first-party code, matched to workspace members by the core) + Path, + /// Any other source (git, alternate registry), kept verbatim for error messages + Other(String), +} + +/// Identity of a package, independent of any input format +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) struct PackageKey { + pub(crate) name: String, + pub(crate) version: Version, + pub(crate) source: SourceKind, +} + +impl fmt::Display for PackageKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}@{}", self.name, self.version)?; + match &self.source { + SourceKind::CratesIo => Ok(()), + SourceKind::Path => write!(f, " (path)"), + SourceKind::Other(source) => write!(f, " ({source})"), + } + } +} + +/// How a package participates in the product +/// +/// Ordered so that the maximum of two roles is the one that wins when merging. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) enum Role { + /// Only used to build the product (build scripts, proc-macros and their dependencies) + BuildTime, + /// Linked into the product + Runtime, +} + +/// What one build of one target proved +#[derive(Debug)] +pub(crate) struct TargetGraph { + root: PackageKey, + packages: BTreeMap, + edges: BTreeSet<(PackageKey, PackageKey)>, +} + +impl TargetGraph { + /// Construct a graph, enforcing the contract's invariants: the root is a member, every edge + /// connects members, and there are no self-edges (they are dropped). + pub(crate) fn new( + root: PackageKey, + packages: BTreeMap, + edges: BTreeSet<(PackageKey, PackageKey)>, + ) -> Result { + if !packages.contains_key(&root) { + return Err(anyhow!("root package {root} is not a member of its graph")); + } + if let Some((from, to)) = edges + .iter() + .find(|(from, to)| !packages.contains_key(from) || !packages.contains_key(to)) + { + return Err(anyhow!( + "dependency edge {from} -> {to} has an unknown endpoint" + )); + } + let edges = edges.into_iter().filter(|(from, to)| from != to).collect(); + Ok(Self { + root, + packages, + edges, + }) + } + + pub(crate) fn root(&self) -> &PackageKey { + &self.root + } + + pub(crate) fn packages(&self) -> &BTreeMap { + &self.packages + } + + pub(crate) fn edges(&self) -> &BTreeSet<(PackageKey, PackageKey)> { + &self.edges + } +} + +#[cfg(test)] +pub(crate) mod test_util { + use super::*; + + /// A crates.io key, for tests + pub(crate) fn key(name: &str, version: &str) -> PackageKey { + PackageKey { + name: name.to_string(), + version: Version::parse(version).unwrap(), + source: SourceKind::CratesIo, + } + } + + /// A path (workspace) key, for tests + pub(crate) fn path_key(name: &str, version: &str) -> PackageKey { + PackageKey { + source: SourceKind::Path, + ..key(name, version) + } + } +} + +#[cfg(test)] +mod tests { + use super::test_util::*; + use super::*; + + #[test] + fn rejects_root_outside_graph() { + let err = TargetGraph::new(key("a", "1.0.0"), BTreeMap::new(), BTreeSet::new()); + assert!(err.is_err()); + } + + #[test] + fn rejects_edge_with_unknown_endpoint() { + let root = key("a", "1.0.0"); + let packages = BTreeMap::from([(root.clone(), Role::Runtime)]); + let edges = BTreeSet::from([(root.clone(), key("b", "1.0.0"))]); + assert!(TargetGraph::new(root, packages, edges).is_err()); + } + + #[test] + fn drops_self_edges() { + let root = key("a", "1.0.0"); + let packages = BTreeMap::from([(root.clone(), Role::Runtime)]); + let edges = BTreeSet::from([(root.clone(), root.clone())]); + let graph = TargetGraph::new(root, packages, edges).unwrap(); + assert!(graph.edges().is_empty()); + } + + #[test] + fn runtime_wins_when_merging_roles() { + assert_eq!(Role::BuildTime.max(Role::Runtime), Role::Runtime); + } +} diff --git a/allow-list/src/input/build_log.rs b/allow-list/src/input/build_log.rs new file mode 100644 index 0000000..09610a2 --- /dev/null +++ b/allow-list/src/input/build_log.rs @@ -0,0 +1,237 @@ +//! Reader for `cargo build --message-format json` logs + +use super::{pkgid, Variant}; +use anyhow::anyhow; +use cargo_metadata::{Message, TargetKind}; +use std::collections::BTreeSet; +use std::io::BufRead; + +/// Kinds of a root artifact that count as a shippable product +const PRODUCT_KINDS: [TargetKind; 6] = [ + TargetKind::Lib, + TargetKind::RLib, + TargetKind::CDyLib, + TargetKind::StaticLib, + TargetKind::DyLib, + TargetKind::Bin, +]; + +/// Kinds that never belong to a product build +const NON_PRODUCT_KINDS: [TargetKind; 3] = + [TargetKind::Example, TargetKind::Test, TargetKind::Bench]; + +/// Read and validate a build log, returning the (package, features) variant of every compiled +/// artifact except build scripts. +/// +/// The log must come from a successful product build of `root`: it must end with a successful +/// `build-finished` message, contain no test/example/bench artifacts, and contain a non-`.rmeta` +/// product artifact for `root` (which rejects `cargo check`). +pub(crate) fn read(log: R, root: &str) -> Result, anyhow::Error> { + let mut variants = BTreeSet::new(); + let mut finished = None; + let mut root_product = false; + + for message in Message::parse_stream(log) { + let message = message?; + if finished.is_some() { + if !matches!(message, Message::TextLine(_)) { + return Err(anyhow!("build log has messages after `build-finished`")); + } + continue; + } + match message { + Message::CompilerArtifact(artifact) => { + if artifact.profile.test + || artifact + .target + .kind + .iter() + .any(|k| NON_PRODUCT_KINDS.contains(k)) + { + return Err(anyhow!( + "build log contains a test, example or bench artifact ({} target {:?}); \ + it must come from a product build", + artifact.package_id, + artifact.target.name + )); + } + if artifact.target.kind.contains(&TargetKind::CustomBuild) { + continue; + } + let key = pkgid::parse(&artifact.package_id.repr)?; + if key.name == root + && artifact + .target + .kind + .iter() + .any(|k| PRODUCT_KINDS.contains(k)) + && artifact + .filenames + .iter() + .any(|f| f.extension() != Some("rmeta")) + { + root_product = true; + } + variants.insert(Variant { + key, + features: artifact.features.into_iter().collect(), + }); + } + Message::BuildFinished(status) => finished = Some(status.success), + Message::TextLine(line) if line.trim_start().starts_with('{') => { + return Err(anyhow!("build log contains a malformed message: {line}")); + } + _ => {} + } + } + + match finished { + None => Err(anyhow!( + "build log has no `build-finished` message (truncated or failed build?)" + )), + Some(false) => Err(anyhow!("build log reports a failed build")), + Some(true) if !root_product => Err(anyhow!( + "build log has no product artifact for root package `{root}` (wrong -p, or `cargo check`?)" + )), + Some(true) => Ok(variants), + } +} + +#[cfg(test)] +pub(crate) mod test_util { + use serde_json::{json, Value}; + + /// A `compiler-artifact` message line + pub(crate) fn artifact(id: &str, kind: &[&str], features: &[&str], file: &str) -> String { + artifact_with(id, kind, features, file, false) + } + + pub(crate) fn artifact_with( + id: &str, + kind: &[&str], + features: &[&str], + file: &str, + test: bool, + ) -> String { + let message: Value = json!({ + "reason": "compiler-artifact", + "package_id": id, + "manifest_path": "/build/Cargo.toml", + "target": { + "kind": kind, + "crate_types": kind, + "name": "target", + "src_path": "/build/src/lib.rs", + "edition": "2021", + "doc": true, + "doctest": true, + "test": true + }, + "profile": { + "opt_level": "3", + "debuginfo": 0, + "debug_assertions": false, + "overflow_checks": false, + "test": test + }, + "features": features, + "filenames": [file], + "executable": null, + "fresh": false + }); + message.to_string() + } + + pub(crate) fn finished(success: bool) -> String { + json!({"reason": "build-finished", "success": success}).to_string() + } +} + +#[cfg(test)] +mod tests { + use super::test_util::*; + use super::*; + use crate::graph::test_util::{key, path_key}; + + const ROOT: &str = "path+file:///build/app#1.0.0"; + const SERDE: &str = "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228"; + + fn log(lines: &[String]) -> String { + lines.join("\n") + } + + fn root_artifact() -> String { + artifact(ROOT, &["rlib", "cdylib"], &["default"], "/t/libapp.so") + } + + #[test] + fn reads_variants_including_fresh_and_skips_build_scripts() { + let text = log(&[ + " Compiling serde v1.0.228".to_string(), + artifact(SERDE, &["custom-build"], &["std"], "/t/build-script-build"), + artifact(SERDE, &["lib"], &["std"], "/t/libserde.rlib"), + artifact(SERDE, &["lib"], &["derive", "std"], "/t/libserde-host.rlib"), + root_artifact(), + finished(true), + ]); + let variant = |key, features: &[&str]| Variant { + key, + features: features.iter().map(|f| f.to_string()).collect(), + }; + let expected = BTreeSet::from([ + variant(key("serde", "1.0.228"), &["std"]), + variant(key("serde", "1.0.228"), &["derive", "std"]), + variant(path_key("app", "1.0.0"), &["default"]), + ]); + assert_eq!(read(text.as_bytes(), "app").unwrap(), expected); + } + + #[test] + fn requires_successful_final_build_finished() { + let missing = log(&[root_artifact()]); + assert!(read(missing.as_bytes(), "app").is_err()); + let failed = log(&[root_artifact(), finished(false)]); + assert!(read(failed.as_bytes(), "app").is_err()); + let after = log(&[finished(true), root_artifact()]); + assert!(read(after.as_bytes(), "app").is_err()); + } + + #[test] + fn rejects_malformed_messages() { + let text = log(&[ + root_artifact(), + "{\"reason\":\"compiler-artifact\",\"truncated".to_string(), + finished(true), + ]); + assert!(read(text.as_bytes(), "app").is_err()); + } + + #[test] + fn rejects_test_example_and_bench_artifacts() { + for bad in [ + artifact_with(SERDE, &["lib"], &[], "/t/libserde.rlib", true), + artifact(ROOT, &["example"], &[], "/t/example"), + artifact(ROOT, &["test"], &[], "/t/test"), + artifact(ROOT, &["bench"], &[], "/t/bench"), + ] { + let text = log(&[root_artifact(), bad, finished(true)]); + assert!(read(text.as_bytes(), "app").is_err()); + } + } + + #[test] + fn requires_a_product_artifact_for_the_root() { + let check = log(&[ + artifact(ROOT, &["lib"], &[], "/t/libapp.rmeta"), + finished(true), + ]); + assert!(read(check.as_bytes(), "app").is_err()); + let wrong_root = log(&[root_artifact(), finished(true)]); + assert!(read(wrong_root.as_bytes(), "other").is_err()); + let plain_lib = log(&[ + artifact(ROOT, &["lib"], &[], "/t/libapp.rlib"), + finished(true), + ]); + assert!(read(plain_lib.as_bytes(), "app").is_ok()); + } +} diff --git a/allow-list/src/input/cargo_tree.rs b/allow-list/src/input/cargo_tree.rs new file mode 100644 index 0000000..a4c4995 --- /dev/null +++ b/allow-list/src/input/cargo_tree.rs @@ -0,0 +1,231 @@ +//! Parser for `cargo tree --prefix depth --color never --format '{p}|{f}'` output +//! +//! Every line has the form +//! +//! ```text +//! v[ (proc-macro)][ ()]|[ (*)] +//! ``` +//! +//! where `(*)` marks a node whose dependencies were already listed earlier. Any other line is an +//! error, so a change in Cargo's output fails loudly instead of silently dropping packages. + +use super::Variant; +use crate::graph::{PackageKey, SourceKind}; +use anyhow::anyhow; +use semver::Version; +use std::collections::BTreeSet; + +/// A parsed dependency tree +#[derive(Debug)] +pub(crate) struct Tree { + /// The package at depth 0 + pub(crate) root: PackageKey, + /// Every (package, enabled features) node in the tree + pub(crate) variants: BTreeSet, + /// Package-level dependency edges, from every expansion in the tree + pub(crate) edges: BTreeSet<(PackageKey, PackageKey)>, +} + +impl Tree { + /// The distinct packages in the tree + pub(crate) fn packages(&self) -> BTreeSet<&PackageKey> { + self.variants.iter().map(|v| &v.key).collect() + } +} + +/// Parse the full text of a `cargo tree` invocation with a single root +pub(crate) fn parse(text: &str) -> Result { + let mut root = None; + let mut variants = BTreeSet::new(); + let mut edges = BTreeSet::new(); + // ancestors[d] is the package most recently seen at depth d + let mut ancestors: Vec = Vec::new(); + // depth of the previous line if it was a `(*)` node, whose children are never listed + let mut previous_deduplicated: Option = None; + + for (index, line) in text.lines().enumerate() { + let line_number = index + 1; + let (depth, variant, deduplicated) = parse_line(line) + .map_err(|err| anyhow!("cargo tree line {line_number}: {err}: {line:?}"))?; + + if previous_deduplicated.is_some_and(|d| depth > d) { + return Err(anyhow!( + "cargo tree line {line_number}: children listed under a `(*)` node" + )); + } + if depth == 0 { + if root.is_some() { + return Err(anyhow!("cargo tree line {line_number}: more than one root")); + } + root = Some(variant.key.clone()); + } else { + let parent = ancestors.get(depth - 1).ok_or_else(|| { + anyhow!("cargo tree line {line_number}: depth {depth} has no parent") + })?; + edges.insert((parent.clone(), variant.key.clone())); + } + ancestors.truncate(depth); + ancestors.push(variant.key.clone()); + previous_deduplicated = deduplicated.then_some(depth); + variants.insert(variant); + } + + let root = root.ok_or_else(|| anyhow!("cargo tree output is empty"))?; + Ok(Tree { + root, + variants, + edges, + }) +} + +/// Parse one line into its depth, variant, and whether it is a deduplicated `(*)` node +fn parse_line(line: &str) -> Result<(usize, Variant, bool), String> { + let (line, deduplicated) = match line.strip_suffix(" (*)") { + Some(rest) => (rest, true), + None => (line, false), + }; + let digits = line + .find(|c: char| !c.is_ascii_digit()) + .unwrap_or(line.len()); + if digits == 0 { + return Err("missing depth prefix (expected `--prefix depth`)".to_string()); + } + let depth = line[..digits] + .parse() + .map_err(|err| format!("invalid depth: {err}"))?; + let (package, features) = line[digits..] + .rsplit_once('|') + .ok_or("missing `|` (expected `--format '{p}|{f}'`)")?; + // Cargo prints the marker between the version and the source + let package = package.replacen(" (proc-macro)", "", 1); + let (name, rest) = package + .split_once(" v") + .ok_or("expected ` v`")?; + let (version, source) = match rest.split_once(" (") { + None => (rest, SourceKind::CratesIo), + Some((version, source)) => { + let source = source.strip_suffix(')').ok_or("unterminated source")?; + (version, source_kind(source)) + } + }; + if name.is_empty() || name.contains(char::is_whitespace) { + return Err("invalid package name".to_string()); + } + let version = Version::parse(version).map_err(|err| format!("invalid version: {err}"))?; + let features = features + .split(',') + .filter(|f| !f.is_empty()) + .map(str::to_string) + .collect(); + let key = PackageKey { + name: name.to_string(), + version, + source, + }; + Ok((depth, Variant { key, features }, deduplicated)) +} + +/// `cargo tree` prints local paths for path packages, and URLs (or `registry ...`) otherwise +fn source_kind(source: &str) -> SourceKind { + let windows_drive = source.as_bytes().get(1..3) == Some(b":\\".as_slice()); + if source.starts_with('/') || source.starts_with("\\\\") || windows_drive { + SourceKind::Path + } else { + SourceKind::Other(source.to_string()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::graph::test_util::{key, path_key}; + + fn variant(key: PackageKey, features: &[&str]) -> Variant { + Variant { + key, + features: features.iter().map(|f| f.to_string()).collect(), + } + } + + #[test] + fn parses_every_line_form() { + let tree = parse(concat!( + "0app v1.0.0 (/build/app)|default,std\n", + "1serde v1.0.228|std\n", + "1serde_derive v1.0.228 (proc-macro)|default\n", + "2serde v1.0.228|std (*)\n", + "1local_macro v0.1.0 (proc-macro) (/build/local_macro)|\n", + "1local v0.1.0 (C:\\build\\local)|\n", + "1gitdep v0.2.0 (https://github.com/x/y#abc123)|\n", + )) + .unwrap(); + assert_eq!(tree.root, path_key("app", "1.0.0")); + assert!(tree + .variants + .contains(&variant(path_key("app", "1.0.0"), &["default", "std"]))); + assert!(tree + .variants + .contains(&variant(key("serde_derive", "1.0.228"), &["default"]))); + assert!(tree + .variants + .contains(&variant(path_key("local", "0.1.0"), &[]))); + let git = tree + .packages() + .into_iter() + .find(|k| k.name == "gitdep") + .unwrap() + .clone(); + assert_eq!( + git.source, + SourceKind::Other("https://github.com/x/y#abc123".to_string()) + ); + assert!(tree + .variants + .contains(&variant(path_key("local_macro", "0.1.0"), &[]))); + assert_eq!(tree.variants.len(), 6); + assert!(tree + .edges + .contains(&(key("serde_derive", "1.0.228"), key("serde", "1.0.228")))); + assert_eq!(tree.edges.len(), 6); + } + + #[test] + fn repeated_expansions_with_different_children_all_contribute_edges() { + // e.g. a host and a target variant of the same package with different dependencies + let tree = parse(concat!( + "0app v1.0.0|\n", + "1dep v1.0.0|target\n", + "2a v1.0.0|\n", + "1tool v1.0.0|\n", + "2dep v1.0.0|host\n", + "3b v1.0.0|\n", + )) + .unwrap(); + assert!(tree + .edges + .contains(&(key("dep", "1.0.0"), key("a", "1.0.0")))); + assert!(tree + .edges + .contains(&(key("dep", "1.0.0"), key("b", "1.0.0")))); + assert_eq!(tree.variants.len(), 6); + assert_eq!(tree.packages().len(), 5); + } + + #[test] + fn rejects_malformed_output() { + for bad in [ + "", + "app v1.0.0|\n", // no depth prefix + "0app v1.0.0\n", // no features + "├── app v1.0.0|\n", // indent prefix + "0app v1.0.0|\n0other v1.0.0|\n", // two roots + "0app v1.0.0|\n2deep v1.0.0|\n", // skipped a level + "0app v1.0.0|\n1a v1.0.0| (*)\n2b v1.0.0|\n", // children under (*) + "0app vnot-a-version|\n", + "0app v1.0.0 (/x|\n", + "0app v1.0.0|\n\n", // blank line + ] { + assert!(parse(bad).is_err(), "accepted {bad:?}"); + } + } +} diff --git a/allow-list/src/input/mod.rs b/allow-list/src/input/mod.rs new file mode 100644 index 0000000..7e8fa45 --- /dev/null +++ b/allow-list/src/input/mod.rs @@ -0,0 +1,177 @@ +//! Input readers: turn one target's raw build evidence into a [`TargetGraph`]. +//! +//! This is the only module that knows input formats. Today there is one reader, which combines +//! a cargo build log with two `cargo tree` outputs produced by the same invocation; see the +//! README for the producer recipe and for what the cross-checks below do and do not prove. + +mod build_log; +mod cargo_tree; +mod pkgid; + +use crate::graph::{PackageKey, Role, TargetGraph}; +use anyhow::{anyhow, Context}; +use std::collections::{BTreeMap, BTreeSet}; +use std::fs::File; +use std::io::BufReader; +use std::path::{Path, PathBuf}; + +/// File names used for each target in a directory of build evidence +const LOG_FILE: &str = "build.json"; +const TREE_FILE: &str = "tree.txt"; +const RUNTIME_TREE_FILE: &str = "runtime-tree.txt"; + +/// A package as compiled with a particular set of enabled features +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +struct Variant { + key: PackageKey, + features: BTreeSet, +} + +/// The build evidence for one target +#[derive(Debug, Clone)] +pub(crate) enum TargetInput { + /// A `cargo build --message-format json` log plus the full (`-e normal,build`) and runtime + /// (`-e normal,no-proc-macro`) `cargo tree` outputs from the same invocation + LogAndTree { + log: PathBuf, + tree: PathBuf, + runtime_tree: PathBuf, + }, +} + +impl std::fmt::Display for TargetInput { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::LogAndTree { log, .. } => write!(f, "{}", log.display()), + } + } +} + +impl TargetInput { + /// The evidence for one target stored in a directory under the standard file names + pub(crate) fn from_dir(dir: &Path) -> Self { + Self::LogAndTree { + log: dir.join(LOG_FILE), + tree: dir.join(TREE_FILE), + runtime_tree: dir.join(RUNTIME_TREE_FILE), + } + } + + /// Read the evidence and produce the graph of the build of `root` + pub(crate) fn read(&self, root: &str) -> Result { + match self { + Self::LogAndTree { + log, + tree, + runtime_tree, + } => { + let compiled = build_log::read(BufReader::new(open(log)?), root) + .with_context(|| format!("reading {}", log.display()))?; + let tree = parse_tree(tree)?; + let runtime = parse_tree(runtime_tree)?; + graph_from_log_and_tree(root, &compiled, tree, &runtime) + } + } + } +} + +fn open(path: &Path) -> Result { + File::open(path).with_context(|| format!("opening {}", path.display())) +} + +fn parse_tree(path: &Path) -> Result { + let text = + std::fs::read_to_string(path).with_context(|| format!("reading {}", path.display()))?; + cargo_tree::parse(&text).with_context(|| format!("parsing {}", path.display())) +} + +/// Cross-check the build log against the trees, then assign roles from the runtime tree +fn graph_from_log_and_tree( + root: &str, + compiled: &BTreeSet, + tree: cargo_tree::Tree, + runtime: &cargo_tree::Tree, +) -> Result { + if tree.root.name != root { + return Err(anyhow!( + "cargo tree root is `{}`, expected `{root}`", + tree.root.name + )); + } + if runtime.root != tree.root { + return Err(anyhow!( + "the runtime tree's root {} differs from the full tree's root {}", + runtime.root, + tree.root + )); + } + + let compiled_packages: BTreeSet<&PackageKey> = compiled.iter().map(|v| &v.key).collect(); + let tree_packages = tree.packages(); + check_same( + "packages", + tree_packages + .difference(&compiled_packages) + .map(|k| k.to_string()), + compiled_packages + .difference(&tree_packages) + .map(|k| k.to_string()), + )?; + check_same( + "(package, features) variants", + tree.variants.difference(compiled).map(Variant::to_string), + compiled.difference(&tree.variants).map(Variant::to_string), + )?; + let not_in_tree: Vec = runtime + .variants + .difference(&tree.variants) + .map(Variant::to_string) + .collect(); + if !not_in_tree.is_empty() { + return Err(anyhow!( + "the runtime tree has variants missing from the full tree (different arguments?): {}", + not_in_tree.join(", ") + )); + } + + let runtime_packages = runtime.packages(); + let packages: BTreeMap = tree_packages + .into_iter() + .map(|key| { + let role = if runtime_packages.contains(key) { + Role::Runtime + } else { + Role::BuildTime + }; + (key.clone(), role) + }) + .collect(); + TargetGraph::new(tree.root, packages, tree.edges) +} + +/// Fail with a description of both differences if either is non-empty +fn check_same( + what: &str, + only_in_tree: impl Iterator, + only_compiled: impl Iterator, +) -> Result<(), anyhow::Error> { + let only_in_tree: Vec = only_in_tree.collect(); + let only_compiled: Vec = only_compiled.collect(); + if only_in_tree.is_empty() && only_compiled.is_empty() { + return Ok(()); + } + Err(anyhow!( + "the build log and cargo tree disagree on {what} (were they produced by the same \ + invocation, in the same environment?)\n in cargo tree but not compiled: {}\n \ + compiled but not in cargo tree: {}", + only_in_tree.join(", "), + only_compiled.join(", ") + )) +} + +impl std::fmt::Display for Variant { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let features: Vec<&str> = self.features.iter().map(String::as_str).collect(); + write!(f, "{} [{}]", self.key, features.join(",")) + } +} diff --git a/allow-list/src/input/pkgid.rs b/allow-list/src/input/pkgid.rs new file mode 100644 index 0000000..4c42569 --- /dev/null +++ b/allow-list/src/input/pkgid.rs @@ -0,0 +1,92 @@ +//! Parsing of Cargo package id strings, as found in build logs (and Cargo's SBOM precursor files) + +use crate::graph::{is_crates_io, PackageKey, SourceKind}; +use anyhow::anyhow; +use semver::Version; + +/// Parse a package id in Cargo's package id spec format (Cargo 1.77+), e.g. +/// +/// * `registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228` +/// * `path+file:///build/dnp3/ffi/dnp3-ffi#1.7.0` (name omitted: it equals the last path segment) +/// * `path+file:///build/dnp3/ffi/schema#dnp3-schema@1.7.0` +pub(crate) fn parse(id: &str) -> Result { + let (url, fragment) = id.split_once('#').ok_or_else(|| { + anyhow!("unsupported package id {id:?}: expected `#@` (Cargo 1.77+)") + })?; + let (name, version) = match fragment.split_once('@') { + Some((name, version)) => (name, version), + None => (last_path_segment(url), fragment), + }; + if name.is_empty() { + return Err(anyhow!("package id {id:?} has no package name")); + } + let version = Version::parse(version) + .map_err(|err| anyhow!("package id {id:?} has an invalid version: {err}"))?; + let source = if is_crates_io(url) { + SourceKind::CratesIo + } else if url.starts_with("path+") { + SourceKind::Path + } else { + SourceKind::Other(url.to_string()) + }; + Ok(PackageKey { + name: name.to_string(), + version, + source, + }) +} + +fn last_path_segment(url: &str) -> &str { + let path = url.split(['?', '#']).next().unwrap_or(url); + path.trim_end_matches('/').rsplit('/').next().unwrap_or("") +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::graph::test_util::{key, path_key}; + + #[test] + fn parses_registry_ids() { + assert_eq!( + parse("registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228").unwrap(), + key("serde", "1.0.228") + ); + assert_eq!( + parse("sparse+https://index.crates.io/#serde@1.0.228").unwrap(), + key("serde", "1.0.228") + ); + } + + #[test] + fn parses_path_ids_with_and_without_name() { + assert_eq!( + parse("path+file:///project/ffi/dnp3-ffi#1.7.0").unwrap(), + path_key("dnp3-ffi", "1.7.0") + ); + assert_eq!( + parse("path+file:///home/user/code/dnp3/ffi/schema#dnp3-schema@1.7.0").unwrap(), + path_key("dnp3-schema", "1.7.0") + ); + } + + #[test] + fn keeps_other_sources() { + let key = parse("git+https://github.com/example/repo?branch=main#thing@0.1.0").unwrap(); + assert_eq!(key.name, "thing"); + assert_eq!( + key.source, + SourceKind::Other("git+https://github.com/example/repo?branch=main".to_string()) + ); + let key = parse("registry+https://my.registry/index#thing@0.1.0").unwrap(); + assert!(matches!(key.source, SourceKind::Other(_))); + } + + #[test] + fn rejects_legacy_and_malformed_ids() { + assert!( + parse("serde 1.0.228 (registry+https://github.com/rust-lang/crates.io-index)").is_err() + ); + assert!(parse("path+file:///project/x#not-a-version").is_err()); + } +} diff --git a/allow-list/src/inventory.rs b/allow-list/src/inventory.rs new file mode 100644 index 0000000..ca66f0c --- /dev/null +++ b/allow-list/src/inventory.rs @@ -0,0 +1,394 @@ +//! Core: merge the per-target graphs and resolve them against the `cargo metadata` dictionary + +use crate::graph::{is_crates_io, PackageKey, Role, SourceKind, TargetGraph}; +use anyhow::anyhow; +use cargo_metadata::{Metadata, Package, PackageId}; +use std::collections::{BTreeMap, BTreeSet, HashMap}; + +/// A package's declared `license` field, parsed and normalized once for every consumer +#[derive(Debug)] +pub(crate) enum DeclaredLicense { + /// A valid SPDX expression, normalized (e.g. legacy `MIT/Apache-2.0` becomes `MIT OR Apache-2.0`) + Valid(Box), + /// No `license` field (the package may only have a `license-file`) + Missing, + /// A `license` field that is not a valid SPDX expression, with the reason + Invalid(String), +} + +/// A package in the product's inventory +#[derive(Debug)] +pub(crate) struct Component<'m> { + pub(crate) package: &'m Package, + pub(crate) role: Role, + /// A workspace member: our own code, needing no approval + pub(crate) first_party: bool, + pub(crate) license: DeclaredLicense, +} + +/// Every package of the product across all targets, resolved against the metadata +#[derive(Debug)] +pub(crate) struct Inventory<'m> { + /// The product itself + pub(crate) root: &'m Package, + /// All other packages, sorted by name, version and id + pub(crate) components: Vec>, + /// Package-level dependency edges, including those from the root + pub(crate) edges: BTreeSet<(&'m PackageId, &'m PackageId)>, +} + +/// Merge the graphs of all targets and resolve every package against the metadata. +/// +/// A package is runtime if it is runtime in any target, or if `embedded` says its code ships +/// even though it is only a build-time dependency. +pub(crate) fn build<'m>( + graphs: &[TargetGraph], + metadata: &'m Metadata, + embedded: impl Fn(&str) -> bool, +) -> Result, anyhow::Error> { + let (first, rest) = graphs + .split_first() + .ok_or_else(|| anyhow!("no build evidence (no target directories?)"))?; + let root_key = first.root(); + if let Some(other) = rest.iter().find(|g| g.root() != root_key) { + return Err(anyhow!( + "targets have different roots: {root_key} and {}", + other.root() + )); + } + + let mut roles: BTreeMap<&PackageKey, Role> = BTreeMap::new(); + let mut key_edges = BTreeSet::new(); + for graph in graphs { + for (key, role) in graph.packages() { + let merged = roles.entry(key).or_insert(*role); + *merged = (*merged).max(*role); + } + key_edges.extend(graph.edges()); + } + + let resolved = resolve(roles.keys().copied(), metadata)?; + let root = resolved[root_key]; + let workspace: BTreeSet<&PackageId> = metadata.workspace_members.iter().collect(); + + let mut components: Vec = roles + .iter() + .filter(|(key, _)| *key != &root_key) + .map(|(key, role)| { + let package = resolved[key]; + let role = if embedded(&package.name) { + Role::Runtime + } else { + *role + }; + Component { + package, + role, + first_party: workspace.contains(&package.id), + license: declared_license(package), + } + }) + .collect(); + components.sort_by(|a, b| { + (&a.package.name, &a.package.version, &a.package.id).cmp(&( + &b.package.name, + &b.package.version, + &b.package.id, + )) + }); + + let edges = key_edges + .into_iter() + .map(|(from, to)| (&resolved[from].id, &resolved[to].id)) + .collect(); + Ok(Inventory { + root, + components, + edges, + }) +} + +/// Resolve each key to exactly one metadata package, reporting every failure at once +fn resolve<'k, 'm>( + keys: impl Iterator, + metadata: &'m Metadata, +) -> Result, anyhow::Error> { + let workspace: BTreeSet<&PackageId> = metadata.workspace_members.iter().collect(); + let mut by_name_version: HashMap<(&str, &semver::Version), Vec<&Package>> = HashMap::new(); + for package in &metadata.packages { + by_name_version + .entry((package.name.as_str(), &package.version)) + .or_default() + .push(package); + } + + let mut resolved = HashMap::new(); + let mut errors = Vec::new(); + for key in keys { + let candidates = by_name_version + .get(&(key.name.as_str(), &key.version)) + .map(Vec::as_slice) + .unwrap_or_default(); + let matching: Vec<&Package> = match &key.source { + SourceKind::CratesIo => candidates + .iter() + .filter(|p| p.source.as_ref().is_some_and(|s| is_crates_io(&s.repr))) + .copied() + .collect(), + SourceKind::Path => candidates + .iter() + .filter(|p| p.source.is_none()) + .copied() + .collect(), + SourceKind::Other(source) => { + errors.push(format!( + "{key}: unsupported source `{source}` (only crates.io and workspace members are supported)" + )); + continue; + } + }; + match matching.as_slice() { + [package] if key.source == SourceKind::Path && !workspace.contains(&package.id) => { + errors.push(format!("{key}: path dependency that is not a workspace member")); + } + [package] => { + resolved.insert(key, *package); + } + [] => errors.push(format!( + "{key}: not found in the cargo metadata (generate it with `--all-features` from the same checkout)" + )), + _ => errors.push(format!("{key}: ambiguous, matches several metadata packages")), + } + } + + if errors.is_empty() { + Ok(resolved) + } else { + Err(anyhow!( + "cannot resolve packages against the cargo metadata:\n {}", + errors.join("\n ") + )) + } +} + +fn declared_license(package: &Package) -> DeclaredLicense { + let Some(declared) = &package.license else { + return DeclaredLicense::Missing; + }; + let normalized = spdx::Expression::canonicalize(declared) + .map(|canonical| canonical.unwrap_or_else(|| declared.clone())) + .and_then(|canonical| spdx::Expression::parse(&canonical)); + match normalized { + Ok(expression) => DeclaredLicense::Valid(Box::new(expression)), + Err(err) => DeclaredLicense::Invalid(err.to_string()), + } +} + +#[cfg(test)] +pub(crate) mod test_util { + use crate::graph::{PackageKey, SourceKind}; + use cargo_metadata::Metadata; + use serde_json::{json, Value}; + + /// A metadata package for a key, with the given declared license + pub(crate) fn package(key: &PackageKey, license: Option<&str>) -> Value { + let id = match key.source { + SourceKind::Path => format!("path+file:///build/{}#{}", key.name, key.version), + _ => format!( + "registry+https://github.com/rust-lang/crates.io-index#{}@{}", + key.name, key.version + ), + }; + let source = match key.source { + SourceKind::Path => Value::Null, + _ => json!("registry+https://github.com/rust-lang/crates.io-index"), + }; + json!({ + "name": key.name, + "version": key.version.to_string(), + "id": id, + "license": license, + "license_file": null, + "description": null, + "source": source, + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": format!("/build/{}/Cargo.toml", key.name), + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }) + } + + /// Metadata for the given packages; path packages are the workspace members + pub(crate) fn metadata(packages: &[(PackageKey, Option<&str>)]) -> Metadata { + let values: Vec = packages.iter().map(|(k, l)| package(k, *l)).collect(); + let members: Vec = values + .iter() + .filter(|p| p["source"].is_null()) + .map(|p| p["id"].clone()) + .collect(); + serde_json::from_value(json!({ + "packages": values, + "workspace_members": members, + "workspace_default_members": members, + "resolve": null, + "workspace_root": "/build", + "target_directory": "/build/target", + "version": 1, + "metadata": null + })) + .unwrap() + } +} + +#[cfg(test)] +mod tests { + use super::test_util::metadata; + use super::*; + use crate::graph::test_util::{key, path_key}; + + fn graph( + root: &PackageKey, + packages: &[(&PackageKey, Role)], + edges: &[(&PackageKey, &PackageKey)], + ) -> TargetGraph { + let mut members: BTreeMap = + packages.iter().map(|(k, r)| ((*k).clone(), *r)).collect(); + members.insert(root.clone(), Role::Runtime); + let edges = edges + .iter() + .map(|(a, b)| ((*a).clone(), (*b).clone())) + .collect(); + TargetGraph::new(root.clone(), members, edges).unwrap() + } + + fn names<'a>(inventory: &'a Inventory, role: Role) -> Vec<&'a str> { + inventory + .components + .iter() + .filter(|c| c.role == role) + .map(|c| c.package.name.as_str()) + .collect() + } + + #[test] + fn merges_targets_with_runtime_winning_and_resolves_against_metadata() { + let app = path_key("app", "1.0.0"); + let (ring, aws, cc, tool) = ( + key("ring", "0.17.14"), + key("aws-lc-rs", "1.18.1"), + key("cc", "1.2.60"), + key("tool", "1.0.0"), + ); + let meta = metadata(&[ + (app.clone(), None), + (ring.clone(), Some("Apache-2.0 AND ISC")), + (aws.clone(), Some("ISC AND (Apache-2.0 OR ISC)")), + (cc.clone(), Some("MIT/Apache-2.0")), + (tool.clone(), None), + ]); + let graphs = [ + graph( + &app, + &[ + (&ring, Role::Runtime), + (&cc, Role::BuildTime), + (&tool, Role::BuildTime), + ], + &[(&app, &ring), (&ring, &cc)], + ), + graph( + &app, + &[(&aws, Role::Runtime), (&cc, Role::Runtime)], + &[(&app, &aws)], + ), + ]; + let inventory = build(&graphs, &meta, |name| name == "tool").unwrap(); + + assert_eq!(inventory.root.name, "app"); + assert_eq!( + names(&inventory, Role::Runtime), + ["aws-lc-rs", "cc", "ring", "tool"] + ); + assert!(names(&inventory, Role::BuildTime).is_empty()); + assert_eq!(inventory.edges.len(), 3); + let cc = inventory + .components + .iter() + .find(|c| c.package.name == "cc") + .unwrap(); + match &cc.license { + DeclaredLicense::Valid(expr) => assert_eq!(expr.to_string(), "MIT OR Apache-2.0"), + other => panic!("unexpected {other:?}"), + } + let tool = inventory + .components + .iter() + .find(|c| c.package.name == "tool") + .unwrap(); + assert!(matches!(tool.license, DeclaredLicense::Missing)); + assert!(!tool.first_party); + } + + #[test] + fn rejects_targets_with_different_roots() { + let (a, b) = (path_key("a", "1.0.0"), path_key("b", "1.0.0")); + let meta = metadata(&[(a.clone(), None), (b.clone(), None)]); + let graphs = [graph(&a, &[], &[]), graph(&b, &[], &[])]; + assert!(build(&graphs, &meta, |_| false).is_err()); + } + + #[test] + fn reports_every_unresolvable_package() { + let app = path_key("app", "1.0.0"); + let missing = key("missing", "1.0.0"); + let git = PackageKey { + source: SourceKind::Other("git+https://example.com/x".to_string()), + ..key("gitdep", "1.0.0") + }; + let stray_path = path_key("vendored", "1.0.0"); + let mut meta = metadata(&[(app.clone(), None), (stray_path.clone(), None)]); + meta.workspace_members + .retain(|id| !id.repr.contains("vendored")); + let graphs = [graph( + &app, + &[ + (&missing, Role::Runtime), + (&git, Role::Runtime), + (&stray_path, Role::Runtime), + ], + &[], + )]; + let err = build(&graphs, &meta, |_| false).unwrap_err().to_string(); + assert!(err.contains("missing@1.0.0: not found"), "{err}"); + assert!(err.contains("unsupported source"), "{err}"); + assert!(err.contains("not a workspace member"), "{err}"); + } + + #[test] + fn flags_invalid_license_expressions() { + let app = path_key("app", "1.0.0"); + let odd = key("odd", "1.0.0"); + let meta = metadata(&[(app.clone(), None), (odd.clone(), Some("MIT AND"))]); + let inventory = build(&[graph(&app, &[(&odd, Role::Runtime)], &[])], &meta, |_| { + false + }) + .unwrap(); + assert!(matches!( + inventory.components[0].license, + DeclaredLicense::Invalid(_) + )); + } +} diff --git a/allow-list/src/licenses.rs b/allow-list/src/licenses.rs index 5e4af7e..a5ad538 100644 --- a/allow-list/src/licenses.rs +++ b/allow-list/src/licenses.rs @@ -191,3 +191,29 @@ fn extract_deps( Ok(deps) } + +#[cfg(test)] +mod tests { + use super::*; + + fn fixture(path: &str) -> std::path::PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")) + .join("tests/fixtures/cyclonedx") + .join(path) + } + + /// The deprecated cargo-cyclonedx commands must keep producing exactly the 0.2.1 output + /// (the expected files were generated with the 0.2.1 release) + #[test] + fn cyclonedx_commands_match_0_2_1_output() { + let mut out = Vec::new(); + gen_licenses_in_dirs(&fixture(""), "bom.json", &fixture("allowed.json"), &mut out).unwrap(); + let expected = std::fs::read_to_string(fixture("expected-dir.txt")).unwrap(); + assert_eq!(String::from_utf8(out).unwrap(), expected); + + let mut out = Vec::new(); + gen_licenses(&fixture("a/bom.json"), &fixture("allowed.json"), &mut out).unwrap(); + let expected = std::fs::read_to_string(fixture("expected-single.txt")).unwrap(); + assert_eq!(String::from_utf8(out).unwrap(), expected); + } +} diff --git a/allow-list/src/log.rs b/allow-list/src/log.rs deleted file mode 100644 index 2533034..0000000 --- a/allow-list/src/log.rs +++ /dev/null @@ -1,123 +0,0 @@ -use crate::config::Config; -use crate::licenses::gen_licenses_for; -use anyhow::anyhow; -use cargo_metadata::{Message, Metadata, Package, PackageId}; -use semver::Version; -use std::collections::btree_map::Entry; -use std::collections::{BTreeMap, BTreeSet, HashMap}; -use std::fs::{read_dir, File}; -use std::io::{BufReader, Write}; -use std::path::Path; - -/// Parse the `cargo metadata --format-version 1` JSON emitted by the build. -/// -/// This is used only as a typed `PackageId -> Package` dictionary for resolving -/// the crates that actually compiled; it never determines scope, so its -/// (superset) package list is harmless. -fn load_metadata(path: &Path) -> Result { - Ok(serde_json::from_reader(BufReader::new(File::open(path)?))?) -} - -/// Read a single `cargo build --message-format=json` log, resolving each -/// compiled artifact's `PackageId` to its typed name and version via `by_id`. -fn read_log_into( - path: &Path, - by_id: &HashMap<&PackageId, &Package>, - deps: &mut BTreeMap>, -) -> Result<(), anyhow::Error> { - let reader = BufReader::new(File::open(path)?); - for message in Message::parse_stream(reader) { - if let Message::CompilerArtifact(artifact) = message? { - // Skip first-party / path dependencies (workspace-local crates). - // Their PackageId embeds an absolute filesystem path that differs - // between the build environment (e.g. a `cross` container mounted at - // /project) and wherever `cargo metadata` ran, so they can't be - // matched by id across environments. They are our own code, not a - // third-party license, so they are excluded from the report anyway. - if artifact.package_id.repr.starts_with("path+") { - continue; - } - // The build log tells us WHICH crates compiled; the metadata gives - // us their typed name/version. Fail closed if the two are out of sync. - let package = by_id.get(&artifact.package_id).ok_or_else(|| { - anyhow!( - "compiled crate {:?} is not present in the cargo metadata; \ - the build log and metadata must come from the same resolution", - artifact.package_id - ) - })?; - match deps.entry(package.name.clone()) { - Entry::Vacant(x) => { - x.insert(BTreeSet::from([package.version.clone()])); - } - Entry::Occupied(mut x) => { - x.get_mut().insert(package.version.clone()); - } - } - } - } - Ok(()) -} - -/// Drop build-only and vendor-licensed packages, matching the cyclonedx path. -fn filter_deps( - mut deps: BTreeMap>, - config: &Config, -) -> BTreeMap> { - deps.retain(|name, _| { - !config.build_only.contains(name) && !config.vendor.contains_key(name) - }); - deps -} - -/// Generate a license summary from a single cargo build log, using the cargo -/// metadata to resolve crate identities and the configuration for the allow-list. -pub(crate) fn gen_licenses_from_log( - log_path: &Path, - metadata_path: &Path, - config_path: &Path, - w: W, -) -> Result<(), anyhow::Error> -where - W: Write, -{ - let config: Config = serde_json::from_reader(BufReader::new(File::open(config_path)?))?; - let metadata = load_metadata(metadata_path)?; - let by_id: HashMap<&PackageId, &Package> = - metadata.packages.iter().map(|p| (&p.id, p)).collect(); - - let mut deps = BTreeMap::new(); - read_log_into(log_path, &by_id, &mut deps)?; - let deps = filter_deps(deps, &config); - gen_licenses_for(&deps, &config, w) -} - -/// Generate a license summary by consolidating one named build log per immediate -/// subdirectory of `list_dir` (mirrors `gen_licenses_in_dirs`), resolved against -/// a single cargo metadata document. -pub(crate) fn gen_licenses_from_log_dir( - list_dir: &Path, - log_file: &str, - metadata_path: &Path, - config_path: &Path, - w: W, -) -> Result<(), anyhow::Error> -where - W: Write, -{ - let config: Config = serde_json::from_reader(BufReader::new(File::open(config_path)?))?; - let metadata = load_metadata(metadata_path)?; - let by_id: HashMap<&PackageId, &Package> = - metadata.packages.iter().map(|p| (&p.id, p)).collect(); - - let mut deps: BTreeMap> = BTreeMap::new(); - for item in read_dir(list_dir)? { - let item = item?; - if item.file_type()?.is_dir() { - read_log_into(&item.path().join(log_file), &by_id, &mut deps)?; - } - } - - let deps = filter_deps(deps, &config); - gen_licenses_for(&deps, &config, w) -} diff --git a/allow-list/src/main.rs b/allow-list/src/main.rs index 5f90788..237fe8f 100644 --- a/allow-list/src/main.rs +++ b/allow-list/src/main.rs @@ -1,12 +1,26 @@ use crate::cli::{Cli, Commands}; use std::io::stdout; +/// approval of the inventory against the allow-list configuration +pub(crate) mod approval; pub(crate) mod cli; +/// command glue: load build evidence, run the core, render an output +pub(crate) mod commands; /// json configuration structures pub mod config; +#[cfg(test)] +mod fixture_tests; +#[cfg(test)] +mod golden_tests; +/// the format-neutral contract between input readers and the core +pub(crate) mod graph; +/// readers that turn build evidence into a per-target graph +pub(crate) mod input; +/// merge per-target graphs and resolve them against the cargo metadata +pub(crate) mod inventory; pub(crate) mod licenses; -/// read cargo build logs (message-format=json) for the actually-compiled dependency set -pub(crate) mod log; +/// CycloneDX SBOM renderer +pub(crate) mod sbom; fn main() -> Result<(), anyhow::Error> { use clap::Parser; @@ -23,16 +37,21 @@ fn main() -> Result<(), anyhow::Error> { bom_file, config_path, } => licenses::gen_licenses_in_dirs(&list_dir, &bom_file, &config_path, stdout()), - Commands::GenLicensesLog { - log_path, - metadata_path, - config_path, - } => log::gen_licenses_from_log(&log_path, &metadata_path, &config_path, stdout()), - Commands::GenLicensesLogDir { - list_dir, - log_file, - metadata_path, - config_path, - } => log::gen_licenses_from_log_dir(&list_dir, &log_file, &metadata_path, &config_path, stdout()), + Commands::GenLicensesLog { target, common } => { + commands::gen_licenses(&target.evidence(common), stdout()) + } + Commands::GenLicensesLogDir { targets, common } => { + commands::gen_licenses(&targets.evidence(common)?, stdout()) + } + Commands::GenSbomLog { + target, + common, + sbom, + } => commands::gen_sbom(&target.evidence(common), &sbom.into(), stdout()), + Commands::GenSbomLogDir { + targets, + common, + sbom, + } => commands::gen_sbom(&targets.evidence(common)?, &sbom.into(), stdout()), } } diff --git a/allow-list/src/sbom.rs b/allow-list/src/sbom.rs new file mode 100644 index 0000000..f3d3933 --- /dev/null +++ b/allow-list/src/sbom.rs @@ -0,0 +1,225 @@ +//! Renderer: a validated inventory as a CycloneDX 1.5 JSON SBOM + +use crate::approval::{Approval, ValidatedInventory}; +use crate::config::CommercialLicense; +use crate::graph::{is_crates_io, Role}; +use crate::inventory::DeclaredLicense; +use anyhow::anyhow; +use cargo_metadata::{Package, PackageId}; +use cyclonedx_bom::models::component::{Classification, Scope}; +use cyclonedx_bom::models::dependency::{Dependencies, Dependency}; +use cyclonedx_bom::models::external_reference::{ + ExternalReference, ExternalReferenceType, ExternalReferences, +}; +use cyclonedx_bom::models::hash::{Hash, HashAlgorithm, HashValue, Hashes}; +use cyclonedx_bom::models::license::{License, LicenseChoice, Licenses}; +use cyclonedx_bom::models::tool::Tools; +use cyclonedx_bom::prelude::*; +use serde::Deserialize; +use std::collections::{BTreeMap, HashMap}; +use std::io::Write; + +/// SHA-256 checksums of crates.io packages, from a `Cargo.lock` +pub(crate) struct Checksums(HashMap<(String, String), String>); + +impl Checksums { + /// Parse the checksums of every crates.io package in a `Cargo.lock` + pub(crate) fn from_lockfile(text: &str) -> Result { + #[derive(Deserialize)] + struct Lockfile { + #[serde(default)] + package: Vec, + } + #[derive(Deserialize)] + struct LockedPackage { + name: String, + version: String, + source: Option, + checksum: Option, + } + let lockfile: Lockfile = toml::from_str(text)?; + Ok(Self( + lockfile + .package + .into_iter() + .filter(|p| p.source.as_deref().is_some_and(is_crates_io)) + .filter_map(|p| Some(((p.name, p.version), p.checksum?))) + .collect(), + )) + } + + fn get(&self, package: &Package) -> Option<&String> { + self.0 + .get(&(package.name.clone(), package.version.to_string())) + } +} + +/// How to produce the document +pub(crate) struct Options<'a> { + /// Add SHA-256 hashes of crates.io packages from this lockfile + pub(crate) checksums: Option<&'a Checksums>, + /// Omit the random serial number, for reproducible output + pub(crate) omit_serial_number: bool, + /// The document's creation time + pub(crate) timestamp: DateTime, +} + +/// Write the SBOM of a validated inventory +pub(crate) fn write( + validated: &ValidatedInventory, + commercial_license: Option<&CommercialLicense>, + options: &Options, + mut w: W, +) -> Result<(), anyhow::Error> { + let commercial_license = commercial_license.ok_or_else(|| { + anyhow!("the configuration needs a `commercial_license` (name and url) to describe first-party and vendor packages") + })?; + let commercial = || { + let mut license = License::named_license(&commercial_license.name); + license.url = Some(Uri::new(&commercial_license.url)); + Licenses(vec![LicenseChoice::License(license)]) + }; + + // every package is referenced by its purl, which must therefore be unique + let root = validated.root; + let packages = + std::iter::once(root).chain(validated.components.iter().map(|a| a.component.package)); + let mut refs: HashMap<&PackageId, String> = HashMap::new(); + for package in packages { + let purl = purl(package)?.to_string(); + if refs.values().any(|r| *r == purl) { + return Err(anyhow!("two packages share the reference {purl}")); + } + refs.insert(&package.id, purl); + } + + let mut root_component = component(root)?; + root_component.licenses = Some(commercial()); + + let mut components = Vec::new(); + for approved in &validated.components { + let package = approved.component.package; + let mut component = component(package)?; + component.scope = Some(match approved.component.role { + Role::Runtime => Scope::Required, + Role::BuildTime => Scope::Excluded, + }); + component.licenses = match &approved.approval { + Approval::FirstParty | Approval::Vendor(_) => Some(commercial()), + Approval::ThirdParty(_) | Approval::BuildOnly => match &approved.component.license { + DeclaredLicense::Valid(expression) => { + Some(Licenses(vec![LicenseChoice::Expression( + SpdxExpression::new(AsRef::::as_ref(&**expression)), + )])) + } + DeclaredLicense::Missing | DeclaredLicense::Invalid(_) => None, + }, + }; + if let Approval::Vendor(vendor) = &approved.approval { + component.external_references = Some(ExternalReferences(vec![ExternalReference::new( + ExternalReferenceType::Vcs, + Uri::new(&vendor.url), + )])); + } + // only crates.io packages reach here besides first-party ones (see `inventory`) + if let (Some(checksums), false) = (options.checksums, approved.component.first_party) { + let checksum = checksums.get(package).ok_or_else(|| { + anyhow!( + "the lockfile has no checksum for {} {}", + package.name, + package.version + ) + })?; + component.hashes = Some(Hashes(vec![Hash { + alg: HashAlgorithm::SHA_256, + content: HashValue(checksum.clone()), + }])); + } + components.push(component); + } + + let mut dependencies: BTreeMap<&str, Vec<&str>> = + refs.values().map(|r| (r.as_str(), Vec::new())).collect(); + for (from, to) in &validated.edges { + if let Some(list) = dependencies.get_mut(refs[from].as_str()) { + list.push(refs[to].as_str()); + } + } + + let tool = Component::new( + Classification::Application, + env!("CARGO_PKG_NAME"), + env!("CARGO_PKG_VERSION"), + None, + ); + let bom = Bom { + spec_version: SpecVersion::V1_5, + serial_number: (!options.omit_serial_number).then(UrnUuid::generate), + metadata: Some(Metadata { + timestamp: Some(options.timestamp.clone()), + tools: Some(Tools::Object { + services: None, + components: Some(Components(vec![tool])), + }), + component: Some(root_component), + ..Metadata::default() + }), + components: Some(Components(components)), + dependencies: Some(Dependencies( + dependencies + .into_iter() + .map(|(from, mut to)| { + to.sort_unstable(); + Dependency { + dependency_ref: from.to_string(), + dependencies: to.into_iter().map(str::to_string).collect(), + } + }) + .collect(), + )), + ..Bom::default() + }; + + let validation = bom.validate_version(SpecVersion::V1_5); + if !validation.passed() { + return Err(anyhow!( + "generated SBOM is not valid CycloneDX 1.5: {validation:?}" + )); + } + let mut json = Vec::new(); + bom.output_as_json_v1_5(&mut json)?; + // cyclonedx-bom writes `"serialNumber": null` when omitted, which the JSON schema rejects + let mut json: serde_json::Value = serde_json::from_slice(&json)?; + if let Some(document) = json.as_object_mut() { + if document + .get("serialNumber") + .is_some_and(serde_json::Value::is_null) + { + document.remove("serialNumber"); + } + } + serde_json::to_writer_pretty(&mut w, &json)?; + writeln!(w)?; + Ok(()) +} + +fn purl(package: &Package) -> Result { + Ok(Purl::new( + "cargo", + &package.name, + &package.version.to_string(), + )?) +} + +/// A library component referenced by its purl +fn component(package: &Package) -> Result { + let purl = purl(package)?; + let mut component = Component::new( + Classification::Library, + &package.name, + &package.version.to_string(), + Some(purl.to_string()), + ); + component.purl = Some(purl); + Ok(component) +} diff --git a/allow-list/tests/fixtures/cyclonedx/a/bom.json b/allow-list/tests/fixtures/cyclonedx/a/bom.json new file mode 100644 index 0000000..9c4aca9 --- /dev/null +++ b/allow-list/tests/fixtures/cyclonedx/a/bom.json @@ -0,0 +1 @@ +{"bomFormat":"CycloneDX","specVersion":"1.4","version":1,"components":[{"type":"library","name":"serde","version":"1.0.228"},{"type":"library","name":"ring","version":"0.17.14"},{"type":"library","name":"cc","version":"1.2.60"},{"type":"library","name":"dnp3","version":"1.7.0"}]} diff --git a/allow-list/tests/fixtures/cyclonedx/allowed.json b/allow-list/tests/fixtures/cyclonedx/allowed.json new file mode 100644 index 0000000..4b5199c --- /dev/null +++ b/allow-list/tests/fixtures/cyclonedx/allowed.json @@ -0,0 +1,9 @@ +{ + "build_only": ["cc"], + "vendor": { "dnp3": { "url": "https://github.com/stepfunc/dnp3" } }, + "third_party": { + "serde": { "id": "serde", "source": "crates.io", "licenses": [{ "MIT": { "copyright": "NotPresent" } }] }, + "ring": { "id": "ring", "source": "crates.io", "licenses": [{ "ISC": { "copyright": { "Lines": ["Copyright 2015-2016 Brian Smith."] } } }, "OpenSSL"] }, + "tokio": { "id": "tokio", "source": "crates.io", "licenses": [{ "MIT": { "copyright": { "Lines": ["Copyright (c) Tokio Contributors"] } } }] } + } +} diff --git a/allow-list/tests/fixtures/cyclonedx/b/bom.json b/allow-list/tests/fixtures/cyclonedx/b/bom.json new file mode 100644 index 0000000..6ca8cd1 --- /dev/null +++ b/allow-list/tests/fixtures/cyclonedx/b/bom.json @@ -0,0 +1 @@ +{"bomFormat":"CycloneDX","specVersion":"1.4","version":1,"components":[{"type":"library","name":"serde","version":"1.0.219"},{"type":"library","name":"tokio","version":"1.52.1"},{"type":"library","name":"dnp3","version":"1.7.0"}]} diff --git a/allow-list/tests/fixtures/cyclonedx/expected-dir.txt b/allow-list/tests/fixtures/cyclonedx/expected-dir.txt new file mode 100644 index 0000000..90d4b6c --- /dev/null +++ b/allow-list/tests/fixtures/cyclonedx/expected-dir.txt @@ -0,0 +1,84 @@ +This distribution contains open source dependencies under the following licenses: + + * ISC + - https://spdx.org/licenses/ISC.html + * MIT + - https://spdx.org/licenses/MIT.html + * OpenSSL + - https://spdx.org/licenses/OpenSSL.html + +Copies of these licenses are provided at the end of this document. They may also be obtained from the URLs above. + +crate: ring +version(s): 0.17.14 +url: https://crates.io/crates/ring +license(s): ISC AND OpenSSL +Copyright 2015-2016 Brian Smith. + +crate: serde +version(s): 1.0.219, 1.0.228 +url: https://crates.io/crates/serde +license(s): MIT +No copyright statement was provided by the author even though they license may refer to it + +crate: tokio +version(s): 1.52.1 +url: https://crates.io/crates/tokio +license(s): MIT +Copyright (c) Tokio Contributors + +=============================== ISC =========================================== + +Permission to use, copy, modify, and /or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +================================= MIT ========================================= + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +================================ OPENSSL======================================= + +Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this software must display the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org. + 5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project. + 6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)" + +THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). This product includes software written by Tim Hudson (tjh@cryptsoft.com). + +Original SSLeay License + +Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) +All rights reserved. + +This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). The implementation was written so as to conform with Netscapes SSL. + +This library is free for commercial and non-commercial use as long as the following conditions are aheared to. The following conditions apply to all code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. The SSL documentation included with this distribution is covered by the same copyright terms except that the holder is Tim Hudson (tjh@cryptsoft.com). + +Copyright remains Eric Young's, and as such any Copyright notices in the code are not to be removed. If this package is used in a product, Eric Young should be given attribution as the author of the parts of the library used. This can be in the form of a textual message at program startup or in documentation (online or textual) provided with the package. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: + "This product includes cryptographic software written by Eric Young (eay@cryptsoft.com)" + The word 'cryptographic' can be left out if the rouines from the library being used are not cryptographic related :-). + 4. If you include any Windows specific code (or a derivative thereof) from the apps directory (application code) you must include an acknowledgement: "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + +THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The licence and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distribution licence [including the GNU Public Licence.] + diff --git a/allow-list/tests/fixtures/cyclonedx/expected-single.txt b/allow-list/tests/fixtures/cyclonedx/expected-single.txt new file mode 100644 index 0000000..af02046 --- /dev/null +++ b/allow-list/tests/fixtures/cyclonedx/expected-single.txt @@ -0,0 +1,78 @@ +This distribution contains open source dependencies under the following licenses: + + * ISC + - https://spdx.org/licenses/ISC.html + * MIT + - https://spdx.org/licenses/MIT.html + * OpenSSL + - https://spdx.org/licenses/OpenSSL.html + +Copies of these licenses are provided at the end of this document. They may also be obtained from the URLs above. + +crate: ring +version(s): 0.17.14 +url: https://crates.io/crates/ring +license(s): ISC AND OpenSSL +Copyright 2015-2016 Brian Smith. + +crate: serde +version(s): 1.0.228 +url: https://crates.io/crates/serde +license(s): MIT +No copyright statement was provided by the author even though they license may refer to it + +=============================== ISC =========================================== + +Permission to use, copy, modify, and /or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +================================= MIT ========================================= + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +================================ OPENSSL======================================= + +Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this software must display the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org. + 5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project. + 6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)" + +THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). This product includes software written by Tim Hudson (tjh@cryptsoft.com). + +Original SSLeay License + +Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) +All rights reserved. + +This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). The implementation was written so as to conform with Netscapes SSL. + +This library is free for commercial and non-commercial use as long as the following conditions are aheared to. The following conditions apply to all code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. The SSL documentation included with this distribution is covered by the same copyright terms except that the holder is Tim Hudson (tjh@cryptsoft.com). + +Copyright remains Eric Young's, and as such any Copyright notices in the code are not to be removed. If this package is used in a product, Eric Young should be given attribution as the author of the parts of the library used. This can be in the form of a textual message at program startup or in documentation (online or textual) provided with the package. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: + "This product includes cryptographic software written by Eric Young (eay@cryptsoft.com)" + The word 'cryptographic' can be left out if the rouines from the library being used are not cryptographic related :-). + 4. If you include any Windows specific code (or a derivative thereof) from the apps directory (application code) you must include an acknowledgement: "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + +THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The licence and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distribution licence [including the GNU Public Licence.] + diff --git a/allow-list/tests/fixtures/dnp3/Cargo.lock b/allow-list/tests/fixtures/dnp3/Cargo.lock new file mode 100644 index 0000000..43f13f3 --- /dev/null +++ b/allow-list/tests/fixtures/dnp3/Cargo.lock @@ -0,0 +1,1326 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "aws-lc-rs" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", + "pkg-config", +] + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cc" +version = "1.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dnp3" +version = "1.7.0" +dependencies = [ + "assert_matches", + "chrono", + "scursor", + "serde", + "serde_json", + "sfio-rustls-config", + "sfio-tokio-mock-io", + "tokio", + "tokio-rustls", + "tokio-serial", + "tracing", + "xxhash-rust", +] + +[[package]] +name = "dnp3-ffi" +version = "1.7.0" +dependencies = [ + "dnp3", + "dnp3-schema", + "lazy_static", + "num_cpus", + "oo-bindgen", + "sfio-promise", + "sfio-tokio-ffi", + "sfio-tracing-ffi", + "tokio", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "dnp3-schema" +version = "1.7.0" +dependencies = [ + "oo-bindgen", + "sfio-tokio-ffi", + "sfio-tracing-ffi", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "mio-serial" +version = "5.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029e1f407e261176a983a6599c084efd322d9301028055c87174beac71397ba3" +dependencies = [ + "log", + "mio", + "nix 0.29.0", + "serialport", + "winapi", +] + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.11.1", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "oo-bindgen" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87847ac8cd3f9ff4bfdb3a23ce104225f7246f37ac1567efe6fc528bb26563b" +dependencies = [ + "backtrace", + "clap", + "dunce", + "heck", + "lazy_static", + "platforms", + "regex", + "semver", + "serde", + "serde_json", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64", + "serde_core", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkcs5" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" +dependencies = [ + "aes", + "cbc", + "der", + "pbkdf2", + "scrypt", + "sha2", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "pkcs5", + "rand_core 0.6.4", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" + +[[package]] +name = "platforms" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d0eef3571242013a0d5dc84861c3ae4a652e56e12adf8bdc26ff5f8cb34c94" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + +[[package]] +name = "rustls" +version = "0.23.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rx509" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b4a7d26e4a603b3cedff6a968d356e445c10dbc3e4cf6bd414fd5428437e73" + +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "pbkdf2", + "salsa20", + "sha2", +] + +[[package]] +name = "scursor" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e9e097d5ccc66dd9a88d94c7ddad0833b13a35ed8f30d6ea28a8d5269cbd58" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serialport" +version = "4.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4d91116f97173694f1642263b2ff837f80d933aa837e2314969f6728f661df3" +dependencies = [ + "bitflags 2.11.1", + "cfg-if", + "core-foundation", + "core-foundation-sys", + "io-kit-sys", + "mach2", + "nix 0.26.4", + "scopeguard", + "unescaper", + "windows-sys 0.52.0", +] + +[[package]] +name = "sfio-promise" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91547be5cac1551a6401a7cfa571524bbcb4d9d818b2756cbe3012b48cc79aaf" + +[[package]] +name = "sfio-rustls-config" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9897a16c2c2da20771fc042228f1484b8166889df83a675704f2926c8fe21778" +dependencies = [ + "pem", + "pkcs8", + "rustls", + "rustls-pki-types", + "rustls-webpki", + "rx509", +] + +[[package]] +name = "sfio-tokio-ffi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f18d418ee525a2027c0b3e1ab34dc050e1f676834b93389829d40aed2bfefecb" +dependencies = [ + "oo-bindgen", +] + +[[package]] +name = "sfio-tracing-ffi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad957e7cc9c0efe86f4a395c0fd063fbb3460bd83fade7bff80188c8eadef35" +dependencies = [ + "oo-bindgen", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tokio" +version = "1.52.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-serial" +version = "5.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa1d5427f11ba7c5e6384521cfd76f2d64572ff29f3f4f7aa0f496282923fdc8" +dependencies = [ + "cfg-if", + "futures", + "log", + "mio-serial", + "serialport", + "tokio", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "chrono", + "nu-ansi-term", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unescaper" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4064ed685c487dbc25bd3f0e9548f2e34bab9d18cefc700f9ec2dba74ba1138e" +dependencies = [ + "thiserror 2.0.18", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/allow-list/tests/fixtures/dnp3/allowed.json b/allow-list/tests/fixtures/dnp3/allowed.json new file mode 100644 index 0000000..6f2f8b2 --- /dev/null +++ b/allow-list/tests/fixtures/dnp3/allowed.json @@ -0,0 +1,2071 @@ +{ + "build_only": [ + "addr2line", + "adler", + "adler2", + "anstream", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "atty", + "autocfg", + "backtrace", + "bindgen", + "cc", + "cexpr", + "cfg_aliases", + "clang-sys", + "clap", + "clap_builder", + "clap_derive", + "clap_lex", + "cmake", + "colorchoice", + "concolor-override", + "concolor-query", + "dunce", + "either", + "errno", + "find-msvc-tools", + "fs_extra", + "gimli", + "glob", + "heck", + "home", + "io-lifetimes", + "is-terminal", + "is_terminal_polyfill", + "itertools", + "lazycell", + "libloading", + "linux-raw-sys", + "mirai-annotations", + "minimal-lexical", + "miniz_oxide", + "nom", + "object", + "once_cell_polyfill", + "os_str_bytes", + "paste", + "pathdiff", + "pest", + "platforms", + "prettyplease", + "proc-macro-error", + "proc-macro-error-attr", + "dnp3-schema", + "rustc-demangle", + "rustc-hash", + "rustix", + "same-file", + "semver", + "semver-parser", + "serde_derive", + "shlex", + "strsim", + "termcolor", + "ucd-trie", + "unicode-segmentation", + "utf8parse", + "version_check", + "walkdir", + "which", + "winapi-util", + "jobserver", + "pkg-config" + ], + "vendor": { + "dnp3": { + "url": "https://github.com/stepfunc/dnp3" + }, + "dnp3-ffi": { + "url": "https://github.com/stepfunc/dnp3" + }, + "dnp3-ffi-java": { + "url": "https://github.com/stepfunc/dnp3" + }, + "sfio-promise": { + "url": "https://github.com/stepfunc/promise" + }, + "sfio-tokio-ffi": { + "url": "https://github.com/stepfunc/tokio-ffi", + "embedded": true + }, + "sfio-tracing-ffi": { + "url": "https://github.com/stepfunc/tracing-ffi", + "embedded": true + } + }, + "third_party": { + "aes": { + "id": "aes", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018 Artyom Pavlov" + ] + } + } + } + ] + }, + "aho-corasick": { + "id": "aho-corasick", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015 Andrew Gallant" + ] + } + } + } + ] + }, + "ansi_term": { + "id": "ansi_term", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 Benjamin Sago" + ] + } + } + } + ] + }, + "base64": { + "id": "base64", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015 Alice Maz" + ] + } + } + } + ] + }, + "base64ct": { + "id": "base64ct", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 Steve \"Sc00bz\" Thomas (steve at tobtu dot com)", + "Copyright (c) 2021 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "bitflags": { + "id": "bitflags", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 The Rust Project Developers" + ] + } + } + } + ] + }, + "block-buffer": { + "id": "block-buffer", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018-2019 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "block-modes": { + "id": "block-modes", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018-2019 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "block-padding": { + "id": "block-padding", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018-2019 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "bytes": { + "id": "bytes", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018 Carl Lerche" + ] + } + } + } + ] + }, + "cbc": { + "id": "cbc", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018-2022 RustCrypto Developers", + "Copyright (c) 2018 Artyom Pavlov" + ] + } + } + } + ] + }, + "cesu8": { + "id": "cesu8", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Eric Kidd" + ] + } + } + } + ] + }, + "cfg-if": { + "id": "cfg-if", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 Alex Crichton" + ] + } + } + } + ] + }, + "chrono": { + "id": "chrono", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014, Kang Seonghoon" + ] + } + } + } + ] + }, + "cipher": { + "id": "cipher", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016-2020 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "combine": { + "id": "combine", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015 Markus Westerlind" + ] + } + } + } + ] + }, + "const-oid": { + "id": "const-oid", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2020-2022 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "CoreFoundation-sys": { + "id": "CoreFoundation-sys", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015 David Cuddeback" + ] + } + } + } + ] + }, + "core-foundation": { + "id": "core-foundation", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2012-2013 Mozilla Foundation" + ] + } + } + } + ] + }, + "core-foundation-sys": { + "id": "core-foundation-sys", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2012-2013 Mozilla Foundation" + ] + } + } + } + ] + }, + "cpufeatures": { + "id": "cpufeatures", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2020 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "crc": { + "id": "crc", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2017 crc-rs Developers" + ] + } + } + } + ] + }, + "crc-catalog": { + "id": "crc-catalog", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Akhil Velagapudi" + ] + } + } + } + ] + }, + "crypto-common": { + "id": "crypto-common", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2021 RustCrypto Developers" + ] + } + } + } + ] + }, + "crypto-mac": { + "id": "crypto-mac", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2021 RustCrypto Developers" + ] + } + } + } + ] + }, + "der": { + "id": "der", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2020-2022 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "digest": { + "id": "digest", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2017 Artyom Pavlov" + ] + } + } + } + ] + }, + "futures": { + "id": "futures", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Alex Crichton", + "Copyright (c) 2017 The Tokio Authors" + ] + } + } + } + ] + }, + "futures-channel": { + "id": "futures-channel", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Alex Crichton", + "Copyright (c) 2017 The Tokio Authors" + ] + } + } + } + ] + }, + "futures-core": { + "id": "futures-core", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Alex Crichton", + "Copyright (c) 2017 The Tokio Authors" + ] + } + } + } + ] + }, + "futures-executor": { + "id": "futures-executor", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Alex Crichton", + "Copyright (c) 2017 The Tokio Authors" + ] + } + } + } + ] + }, + "futures-io": { + "id": "futures-io", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Alex Crichton", + "Copyright (c) 2017 The Tokio Authors" + ] + } + } + } + ] + }, + "futures-macro": { + "id": "futures-macro", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Alex Crichton", + "Copyright (c) 2017 The Tokio Authors" + ] + } + } + } + ] + }, + "futures-sink": { + "id": "futures-sink", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Alex Crichton", + "Copyright (c) 2017 The Tokio Authors" + ] + } + } + } + ] + }, + "futures-task": { + "id": "futures-task", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Alex Crichton", + "Copyright (c) 2017 The Tokio Authors" + ] + } + } + } + ] + }, + "futures-util": { + "id": "futures-util", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Alex Crichton", + "Copyright (c) 2017 The Tokio Authors" + ] + } + } + } + ] + }, + "generic-array": { + "id": "generic-array", + "source": "crates.io", + "authors": null, + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015 Bart\u0142omiej Kami\u0144ski" + ] + } + } + } + ] + }, + "getrandom": { + "id": "getrandom", + "source": "crates.io", + "authors": null, + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018-2024 The rust-random Project Developers", + "Copyright (c) 2014 The Rust Project Developers" + ] + } + } + } + ] + }, + "hmac": { + "id": "hmac", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2017 Artyom Pavlov" + ] + } + } + } + ] + }, + "IOKit-sys": { + "id": "IOKit-sys", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015 David Cuddeback" + ] + } + } + } + ] + }, + "iana-time-zone": { + "id": "iana-time-zone", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2020 Andrew D. Straw" + ] + } + } + } + ] + }, + "inout": { + "id": "inout", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2022 The RustCrypto Project Developers", + "Copyright (c) 2022 Artyom Pavlov" + ] + } + } + } + ] + }, + "io-kit-sys": { + "id": "io-kit-sys", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2017-2018 Junji Takakura" + ] + } + } + } + ] + }, + "itoa": { + "id": "itoa", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": "NotPresent" + } + } + ] + }, + "jni": { + "id": "jni", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Prevoty, Inc. and jni-rs contributors" + ] + } + } + } + ] + }, + "jni-sys": { + "id": "jni-sys", + "source": "crates.io", + "authors": null, + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015 The rust-jni-sys Developers" + ] + } + } + } + ] + }, + "jni-sys-macros": { + "id": "jni-sys-macros", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015 The rust-jni-sys Developers" + ] + } + } + } + ] + }, + "lazy_static": { + "id": "lazy_static", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2010 The Rust Project Developers" + ] + } + } + } + ] + }, + "libc": { + "id": "libc", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014-2020 The Rust Project Developers" + ] + } + } + } + ] + }, + "log": { + "id": "log", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 The Rust Project Developers" + ] + } + } + } + ] + }, + "mach": { + "id": "mach", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Nick Fitzgerald" + ] + } + } + } + ] + }, + "mach2": { + "id": "mach2", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Nick Fitzgerald, 2021 Yuki Okushi" + ] + } + } + } + ] + }, + "matchers": { + "id": "matchers", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Eliza Weisman" + ] + } + } + } + ] + }, + "memchr": { + "id": "memchr", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015 Andrew Gallant" + ] + } + } + } + ] + }, + "memoffset": { + "id": "memoffset", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2017 Gilad Naaman" + ] + } + } + } + ] + }, + "mio": { + "id": "mio", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 Carl Lerche and other MIO contributors" + ] + } + } + } + ] + }, + "mio-serial": { + "id": "mio-serial", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2017 Zac Berkowitz (zac.berkowitz@gmail.com)" + ] + } + } + } + ] + }, + "nix": { + "id": "nix", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015 Carl Lerche + nix-rust Authors" + ] + } + } + } + ] + }, + "nu-ansi-term": { + "id": "nu-ansi-term", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 Benjamin Sago", + "Copyright (c) 2021-2022 The Nushell Project Developers" + ] + } + } + } + ] + }, + "num-integer": { + "id": "num-integer", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 The Rust Project Developers" + ] + } + } + } + ] + }, + "num-traits": { + "id": "num-traits", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 The Rust Project Developers" + ] + } + } + } + ] + }, + "num_cpus": { + "id": "num_cpus", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015" + ] + } + } + } + ] + }, + "once_cell": { + "id": "once_cell", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": "NotPresent" + } + } + ] + }, + "opaque-debug": { + "id": "opaque-debug", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018-2019 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "overload": { + "id": "opaque-debug", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018-2019 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "pbkdf2": { + "id": "pbkdf2", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2017 Artyom Pavlov", + "Copyright (c) 2018-2021 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "pem": { + "id": "pem", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Jonathan Creekmore" + ] + } + } + } + ] + }, + "pem-rfc7468": { + "id": "pem-rfc7468", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2021 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "pin-project-lite": { + "id": "pin-project-lite", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": "NotPresent" + } + } + ] + }, + "pin-utils": { + "id": "pin-utils", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018 The pin-utils authors" + ] + } + } + } + ] + }, + "pkcs5": { + "id": "pkcs5", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2021 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "pkcs8": { + "id": "pkcs8", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2020 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "proc-macro2": { + "id": "proc-macro2", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 Alex Crichton" + ] + } + } + } + ] + }, + "quote": { + "id": "quote", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 The Rust Project Developers" + ] + } + } + } + ] + }, + "rand_core": { + "id": "rand_core", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright 2018 Developers of the Rand project", + "Copyright (c) 2014 The Rust Project Developers" + ] + } + } + } + ] + }, + "regex": { + "id": "regex", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 The Rust Project Developers" + ] + } + } + } + ] + }, + "regex-automata": { + "id": "regex-automata", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015 Andrew Gallant" + ] + } + } + } + ] + }, + "regex-syntax": { + "id": "regex-syntax", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 The Rust Project Developers" + ] + } + } + } + ] + }, + "ring": { + "id": "ring", + "source": "crates.io", + "licenses": [ + "Apache2", + { + "ISC": { + "copyright": "NotPresent" + } + } + ] + }, + "rustls": { + "id": "rustls", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Joseph Birr-Pixton " + ] + } + } + } + ] + }, + "rustls-pki-types": { + "id": "rustls-pki-types", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2023 Dirkjan Ochtman " + ] + } + } + } + ] + }, + "rustls-webpki": { + "id": "rustls-webpki", + "source": "crates.io", + "licenses": [ + { + "ISC": { + "copyright": { + "Lines": [ + "Copyright 2015 Brian Smith." + ] + } + } + } + ] + }, + "ryu": { + "id": "ryu", + "source": "crates.io", + "licenses": [ + "BSLv1" + ] + }, + "salsa20": { + "id": "salsa20", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Eric McCorkle" + ] + } + } + } + ] + }, + "scopeguard": { + "id": "scopeguard", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016-2019 Ulrik Sverdrup \"bluss\" and scopeguard developers" + ] + } + } + } + ] + }, + "scrypt": { + "id": "scrypt", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2021 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "sct": { + "id": "sct", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 Joseph Birr-Pixton " + ] + } + } + } + ] + }, + "serde": { + "id": "serde", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": "NotPresent" + } + } + ] + }, + "serde_core": { + "id": "serde_core", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": "NotPresent" + } + } + ] + }, + "serde_json": { + "id": "serde_json", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": "NotPresent" + } + } + ] + }, + "serialport": { + "id": "serialport", + "source": "crates.io", + "licenses": [ + "MPLv2" + ] + }, + "sha2": { + "id": "sha2", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2006-2009 Graydon Hoare", + "Copyright (c) 2009-2013 Mozilla Foundation", + "Copyright (c) 2016 Artyom Pavlov" + ] + } + } + } + ] + }, + "sharded-slab": { + "id": "sharded-slab", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Eliza Weisman" + ] + } + } + } + ] + }, + "slab": { + "id": "slab", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Carl Lerche" + ] + } + } + } + ] + }, + "smallvec": { + "id": "smallvec", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018 The Servo Project Developers" + ] + } + } + } + ] + }, + "socket2": { + "id": "socket2", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 Alex Crichton" + ] + } + } + } + ] + }, + "spin": { + "id": "spin", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 Mathijs van de Nes" + ] + } + } + } + ] + }, + "spki": { + "id": "spki", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2021-2022 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "static_assertions": { + "id": "static_assertions", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2017 Nikolai Vazquez" + ] + } + } + } + ] + }, + "subtle": { + "id": "subtle", + "source": "crates.io", + "licenses": [ + { + "BSD3": { + "copyright": { + "Lines": [ + "Copyright (c) 2016-2017 Isis Agora Lovecruft, Henry de Valence. All rights reserved." + ] + } + } + } + ] + }, + "syn": { + "id": "syn", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": "NotPresent" + } + } + ] + }, + "thiserror": { + "id": "thiserror", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": "NotPresent" + } + } + ] + }, + "thiserror-impl": { + "id": "thiserror-impl", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": "NotPresent" + } + } + ] + }, + "thread_local": { + "id": "thread_local", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2016 The Rust Project Developers" + ] + } + } + } + ] + }, + "tokio": { + "id": "tokio", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2022 Tokio Contributors" + ] + } + } + } + ] + }, + "time": { + "id": "time", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2022 Jacob Pratt et al." + ] + } + } + } + ] + }, + "tokio-macros": { + "id": "tokio-macros", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2022 Tokio Contributors" + ] + } + } + } + ] + }, + "tokio-rustls": { + "id": "tokio-rustls", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Tokio Contributors" + ] + } + } + } + ] + }, + "tokio-serial": { + "id": "tokio-serial", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2017 Zac Berkowitz and other tokio-serial contributors." + ] + } + } + } + ] + }, + "tracing": { + "id": "tracing", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Tokio Contributors" + ] + } + } + } + ] + }, + "tracing-attributes": { + "id": "tracing-attributes", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Tokio Contributors" + ] + } + } + } + ] + }, + "tracing-core": { + "id": "tracing-core", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Tokio Contributors" + ] + } + } + } + ] + }, + "tracing-log": { + "id": "tracing-log", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Tokio Contributors" + ] + } + } + } + ] + }, + "tracing-serde": { + "id": "tracing-serde", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Tokio Contributors" + ] + } + } + } + ] + }, + "tracing-subscriber": { + "id": "tracing-subscriber", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2019 Tokio Contributors" + ] + } + } + } + ] + }, + "typenum": { + "id": "typenum", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2014 Paho Lurie-Gregg" + ] + } + } + } + ] + }, + "unescaper": { + "id": "unescaper", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2023 Hack Ink" + ] + } + } + } + ] + }, + "unicode-ident": { + "id": "unicode-ident", + "source": "crates.io", + "licenses": [ + "UnicodeDFS2016", + { + "MIT": { + "copyright": "NotPresent" + } + } + ] + }, + "untrusted": { + "id": "untrusted", + "source": "crates.io", + "licenses": [ + { + "ISC": { + "copyright": { + "Lines": [ + "Copyright 2015-2016 Brian Smith." + ] + } + } + } + ] + }, + "winapi": { + "id": "winapi", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2015-2018 The winapi-rs Developers" + ] + } + } + } + ] + }, + "windows-link": { + "id": "windows-link", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) Microsoft Corporation" + ] + } + } + } + ] + }, + "windows-sys": { + "id": "windows-sys", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) Microsoft Corporation" + ] + } + } + } + ] + }, + "windows-targets": { + "id": "windows-targets", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) Microsoft Corporation" + ] + } + } + } + ] + }, + "windows_x86_64_msvc": { + "id": "windows_x86_64_msvc", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) Microsoft Corporation" + ] + } + } + } + ] + }, + "windows_i686_msvc": { + "id": "windows_i686_msvc", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) Microsoft Corporation" + ] + } + } + } + ] + }, + "xxhash-rust": { + "id": "xxhash-rust", + "source": "crates.io", + "licenses": [ + "BSLv1" + ] + }, + "zeroize": { + "id": "zeroize", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) 2018-2021 The RustCrypto Project Developers" + ] + } + } + } + ] + }, + "zmij": { + "id": "zmij", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": "NotPresent" + } + } + ] + }, + "rx509": { + "id": "rx509", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) Step Function I/O LLC" + ] + } + } + } + ] + }, + "scursor": { + "id": "scursor", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) Step Function I/O LLC" + ] + } + } + } + ] + }, + "sfio-rustls-config": { + "id": "sfio-rustls-config", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) Step Function I/O LLC" + ] + } + } + } + ] + }, + "oo-bindgen": { + "id": "oo-bindgen", + "source": "crates.io", + "licenses": [ + { + "MIT": { + "copyright": { + "Lines": [ + "Copyright (c) Step Function I/O LLC" + ] + } + } + } + ], + "embedded": true + }, + "aws-lc-rs": { + "id": "aws-lc-rs", + "source": "crates.io", + "licenses": [ + { + "ISC": { + "copyright": "NotPresent" + } + } + ] + }, + "aws-lc-sys": { + "id": "aws-lc-sys", + "source": "crates.io", + "licenses": [ + { + "ISC": { + "copyright": "NotPresent" + } + }, + "Apache2", + { + "MIT": { + "copyright": "NotPresent" + } + }, + { + "BSD3": { + "copyright": "NotPresent" + } + } + ] + } + }, + "commercial_license": { + "name": "Step Function I/O License Agreement", + "url": "https://github.com/stepfunc/dnp3/blob/main/LICENSE.txt" + } +} \ No newline at end of file diff --git a/allow-list/tests/fixtures/dnp3/metadata.json b/allow-list/tests/fixtures/dnp3/metadata.json new file mode 100644 index 0000000..69ee7ee --- /dev/null +++ b/allow-list/tests/fixtures/dnp3/metadata.json @@ -0,0 +1,6723 @@ +{ + "packages": [ + { + "name": "addr2line", + "version": "0.25.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#addr2line@0.25.1", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/addr2line-0.25.1/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [ + "development-tools::debugging" + ], + "keywords": [ + "DWARF", + "debug", + "elf", + "symbolicate", + "atos" + ], + "readme": null, + "repository": "https://github.com/gimli-rs/addr2line", + "homepage": null, + "documentation": "https://docs.rs/addr2line", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.81" + }, + { + "name": "adler2", + "version": "2.0.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#adler2@2.0.1", + "license": "0BSD OR MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/adler2-2.0.1/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "rustdoc-args": [ + "--cfg=docsrs" + ] + } + }, + "release": { + "no-dev-version": true, + "pre-release-commit-message": "Release {{version}}", + "tag-message": "{{version}}", + "pre-release-replacements": [ + { + "file": "CHANGELOG.md", + "replace": "## Unreleased\n\nNo changes.\n\n## [{{version}} - {{date}}](https://github.com/jonas-schievink/adler/releases/tag/v{{version}})\n", + "search": "## Unreleased\n" + }, + { + "file": "README.md", + "replace": "adler = \"{{version}}\"", + "search": "adler = \"[a-z0-9\\\\.-]+\"" + }, + { + "file": "src/lib.rs", + "replace": "https://docs.rs/adler/{{version}}", + "search": "https://docs.rs/adler/[a-z0-9\\.-]+" + } + ] + } + }, + "publish": null, + "authors": [ + "Jonas Schievink ", + "oyvindln " + ], + "categories": [ + "algorithms" + ], + "keywords": [ + "checksum", + "integrity", + "hash", + "adler32", + "zlib" + ], + "readme": null, + "repository": "https://github.com/oyvindln/adler2", + "homepage": null, + "documentation": "https://docs.rs/adler2/", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "aes", + "version": "0.8.4", + "id": "registry+https://github.com/rust-lang/crates.io-index#aes@0.8.4", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aes-0.8.4/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "crypto", + "aes", + "rijndael", + "block-cipher" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/block-ciphers", + "homepage": null, + "documentation": "https://docs.rs/aes", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.56" + }, + { + "name": "aho-corasick", + "version": "1.1.4", + "id": "registry+https://github.com/rust-lang/crates.io-index#aho-corasick@1.1.4", + "license": "Unlicense OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs", + "--generate-link-to-definition" + ] + } + } + }, + "publish": null, + "authors": [ + "Andrew Gallant " + ], + "categories": [ + "text-processing" + ], + "keywords": [ + "string", + "search", + "text", + "pattern", + "multi" + ], + "readme": null, + "repository": "https://github.com/BurntSushi/aho-corasick", + "homepage": "https://github.com/BurntSushi/aho-corasick", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.60.0" + }, + { + "name": "anstream", + "version": "1.0.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#anstream@1.0.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstream-1.0.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs", + "--generate-link-to-definition" + ] + } + }, + "release": { + "pre-release-replacements": [ + { + "file": "CHANGELOG.md", + "search": "Unreleased", + "replace": "{{version}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "\\.\\.\\.HEAD", + "replace": "...{{tag_name}}", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "ReleaseDate", + "replace": "{{date}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n## [Unreleased] - ReleaseDate\n", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n[Unreleased]: https://github.com/rust-cli/anstyle/compare/{{tag_name}}...HEAD", + "exactly": 1 + } + ] + } + }, + "publish": null, + "authors": [], + "categories": [ + "command-line-interface" + ], + "keywords": [ + "ansi", + "terminal", + "color", + "strip", + "wincon" + ], + "readme": null, + "repository": "https://github.com/rust-cli/anstyle.git", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.66.0" + }, + { + "name": "anstyle", + "version": "1.0.14", + "id": "registry+https://github.com/rust-lang/crates.io-index#anstyle@1.0.14", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-1.0.14/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--generate-link-to-definition" + ] + } + }, + "release": { + "tag-prefix": "", + "pre-release-replacements": [ + { + "file": "CHANGELOG.md", + "search": "Unreleased", + "replace": "{{version}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "\\.\\.\\.HEAD", + "replace": "...{{tag_name}}", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "ReleaseDate", + "replace": "{{date}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n## [Unreleased] - ReleaseDate\n", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n[Unreleased]: https://github.com/rust-cli/anstyle/compare/{{tag_name}}...HEAD", + "exactly": 1 + } + ] + } + }, + "publish": null, + "authors": [], + "categories": [ + "command-line-interface" + ], + "keywords": [ + "ansi", + "terminal", + "color", + "no_std" + ], + "readme": null, + "repository": "https://github.com/rust-cli/anstyle.git", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.66.0" + }, + { + "name": "anstyle-parse", + "version": "1.0.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#anstyle-parse@1.0.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-parse-1.0.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs", + "--generate-link-to-definition" + ] + } + }, + "release": { + "pre-release-replacements": [ + { + "file": "CHANGELOG.md", + "search": "Unreleased", + "replace": "{{version}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "\\.\\.\\.HEAD", + "replace": "...{{tag_name}}", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "ReleaseDate", + "replace": "{{date}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n## [Unreleased] - ReleaseDate\n", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n[Unreleased]: https://github.com/rust-cli/anstyle/compare/{{tag_name}}...HEAD", + "exactly": 1 + } + ] + } + }, + "publish": null, + "authors": [], + "categories": [ + "command-line-interface" + ], + "keywords": [ + "ansi", + "terminal", + "color", + "vte" + ], + "readme": null, + "repository": "https://github.com/rust-cli/anstyle.git", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.66.0" + }, + { + "name": "anstyle-query", + "version": "1.1.5", + "id": "registry+https://github.com/rust-lang/crates.io-index#anstyle-query@1.1.5", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-query-1.1.5/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs", + "--generate-link-to-definition" + ] + } + }, + "release": { + "pre-release-replacements": [ + { + "file": "CHANGELOG.md", + "search": "Unreleased", + "replace": "{{version}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "\\.\\.\\.HEAD", + "replace": "...{{tag_name}}", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "ReleaseDate", + "replace": "{{date}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n## [Unreleased] - ReleaseDate\n", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n[Unreleased]: https://github.com/rust-cli/anstyle/compare/{{tag_name}}...HEAD", + "exactly": 1 + } + ] + } + }, + "publish": null, + "authors": [], + "categories": [ + "command-line-interface" + ], + "keywords": [ + "cli", + "color", + "no-std", + "terminal", + "ansi" + ], + "readme": null, + "repository": "https://github.com/rust-cli/anstyle.git", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.66.0" + }, + { + "name": "autocfg", + "version": "1.5.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#autocfg@1.5.0", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/autocfg-1.5.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Josh Stone " + ], + "categories": [ + "development-tools::build-utils" + ], + "keywords": [ + "rustc", + "build", + "autoconf" + ], + "readme": null, + "repository": "https://github.com/cuviper/autocfg", + "homepage": null, + "documentation": "https://docs.rs/autocfg/", + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": "1.0" + }, + { + "name": "aws-lc-rs", + "version": "1.18.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#aws-lc-rs@1.18.1", + "license": "ISC AND (Apache-2.0 OR ISC)", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-rs-1.18.1/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "rustdoc-args": [ + "--cfg", + "aws_lc_rs_docsrs" + ], + "features": [ + "unstable", + "legacy-des" + ] + } + }, + "cargo-udeps": { + "ignore": { + "development": [ + "which", + "home", + "regex", + "regex-automata", + "regex-syntax", + "proc-macro2", + "jobserver", + "cc", + "once_cell" + ] + } + } + }, + "publish": null, + "authors": [ + "AWS-LibCrypto" + ], + "categories": [], + "keywords": [ + "crypto", + "cryptography", + "security" + ], + "readme": null, + "repository": "https://github.com/aws/aws-lc-rs", + "homepage": "https://github.com/aws/aws-lc-rs", + "documentation": "https://docs.rs/crate/aws-lc-rs", + "edition": "2021", + "links": "aws_lc_rs_1_18_1_sys", + "default_run": null, + "rust_version": "1.71.0" + }, + { + "name": "aws-lc-sys", + "version": "0.45.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#aws-lc-sys@0.45.0", + "license": "ISC AND (Apache-2.0 OR ISC) AND Apache-2.0 AND MIT AND BSD-3-Clause AND (Apache-2.0 OR ISC OR MIT) AND (Apache-2.0 OR ISC OR MIT-0)", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-sys-0.45.0/Cargo.toml", + "metadata": { + "aws-lc-sys": { + "commit-hash": "02561621ffa4cf17c0c4f70bc11a82df36b42ae9" + } + }, + "publish": null, + "authors": [ + "AWS-LC" + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/aws/aws-lc-rs", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": "aws_lc_0_45_0", + "default_run": null, + "rust_version": "1.71.0" + }, + { + "name": "backtrace", + "version": "0.3.76", + "id": "registry+https://github.com/rust-lang/crates.io-index#backtrace@0.3.76", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/backtrace-0.3.76/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "The Rust Project Developers" + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/backtrace-rs", + "homepage": "https://github.com/rust-lang/backtrace-rs", + "documentation": "https://docs.rs/backtrace", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.82.0" + }, + { + "name": "base64", + "version": "0.22.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#base64@0.22.1", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/base64-0.22.1/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "rustdoc-args": [ + "--generate-link-to-definition" + ] + } + } + }, + "publish": null, + "authors": [ + "Marshall Pierce " + ], + "categories": [ + "encoding" + ], + "keywords": [ + "base64", + "utf8", + "encode", + "decode", + "no_std" + ], + "readme": null, + "repository": "https://github.com/marshallpierce/rust-base64", + "homepage": null, + "documentation": "https://docs.rs/base64", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.48.0" + }, + { + "name": "base64ct", + "version": "1.8.3", + "id": "registry+https://github.com/rust-lang/crates.io-index#base64ct@1.8.3", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/base64ct-1.8.3/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "encoding", + "no-std", + "parser-implementations" + ], + "keywords": [ + "crypto", + "base64", + "pem", + "phc" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/formats", + "homepage": "https://github.com/RustCrypto/formats/tree/master/base64ct", + "documentation": "https://docs.rs/base64ct", + "edition": "2024", + "links": null, + "default_run": null, + "rust_version": "1.85" + }, + { + "name": "bitflags", + "version": "1.3.2", + "id": "registry+https://github.com/rust-lang/crates.io-index#bitflags@1.3.2", + "license": "MIT/Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bitflags-1.3.2/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "example_generated" + ] + } + } + }, + "publish": null, + "authors": [ + "The Rust Project Developers" + ], + "categories": [ + "no-std" + ], + "keywords": [ + "bit", + "bitmask", + "bitflags", + "flags" + ], + "readme": null, + "repository": "https://github.com/bitflags/bitflags", + "homepage": "https://github.com/bitflags/bitflags", + "documentation": "https://docs.rs/bitflags", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "bitflags", + "version": "2.11.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#bitflags@2.11.1", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bitflags-2.11.1/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "example_generated" + ] + } + } + }, + "publish": null, + "authors": [ + "The Rust Project Developers" + ], + "categories": [ + "no-std" + ], + "keywords": [ + "bit", + "bitmask", + "bitflags", + "flags" + ], + "readme": null, + "repository": "https://github.com/bitflags/bitflags", + "homepage": "https://github.com/bitflags/bitflags", + "documentation": "https://docs.rs/bitflags", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.56.0" + }, + { + "name": "block-buffer", + "version": "0.10.4", + "id": "registry+https://github.com/rust-lang/crates.io-index#block-buffer@0.10.4", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "block", + "buffer" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/utils", + "homepage": null, + "documentation": "https://docs.rs/block-buffer", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "block-padding", + "version": "0.3.3", + "id": "registry+https://github.com/rust-lang/crates.io-index#block-padding@0.3.3", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-padding-0.3.3/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "padding", + "pkcs7", + "ansix923", + "iso7816" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/utils", + "homepage": null, + "documentation": "https://docs.rs/block-padding", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.56" + }, + { + "name": "bytes", + "version": "1.11.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#bytes@1.11.1", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.11.1/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "Carl Lerche ", + "Sean McArthur " + ], + "categories": [ + "network-programming", + "data-structures" + ], + "keywords": [ + "buffers", + "zero-copy", + "io" + ], + "readme": null, + "repository": "https://github.com/tokio-rs/bytes", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.57" + }, + { + "name": "cbc", + "version": "0.1.2", + "id": "registry+https://github.com/rust-lang/crates.io-index#cbc@0.1.2", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cbc-0.1.2/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "crypto", + "block-mode", + "ciphers" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/block-modes", + "homepage": null, + "documentation": "https://docs.rs/cbc", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.56" + }, + { + "name": "cc", + "version": "1.2.60", + "id": "registry+https://github.com/rust-lang/crates.io-index#cc@1.2.60", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cc-1.2.60/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Alex Crichton " + ], + "categories": [ + "development-tools::build-utils" + ], + "keywords": [ + "build-dependencies" + ], + "readme": null, + "repository": "https://github.com/rust-lang/cc-rs", + "homepage": "https://github.com/rust-lang/cc-rs", + "documentation": "https://docs.rs/cc", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.63" + }, + { + "name": "cfg-if", + "version": "1.0.4", + "id": "registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg-if-1.0.4/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Alex Crichton " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/cfg-if", + "homepage": null, + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.32" + }, + { + "name": "cfg_aliases", + "version": "0.2.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#cfg_aliases@0.2.1", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg_aliases-0.2.1/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Zicklag " + ], + "categories": [ + "development-tools", + "development-tools::build-utils" + ], + "keywords": [ + "cfg", + "alias", + "conditional", + "compilation", + "build" + ], + "readme": null, + "repository": "https://github.com/katharostech/cfg_aliases", + "homepage": "https://github.com/katharostech/cfg_aliases", + "documentation": "https://docs.rs/cfg_aliases", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "chrono", + "version": "0.4.44", + "id": "registry+https://github.com/rust-lang/crates.io-index#chrono@0.4.44", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "arbitrary", + "rkyv", + "serde", + "unstable-locales" + ], + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + }, + "playground": { + "features": [ + "serde" + ] + } + }, + "publish": null, + "authors": [], + "categories": [ + "date-and-time" + ], + "keywords": [ + "date", + "time", + "calendar" + ], + "readme": null, + "repository": "https://github.com/chronotope/chrono", + "homepage": "https://github.com/chronotope/chrono", + "documentation": "https://docs.rs/chrono/", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.62.0" + }, + { + "name": "cipher", + "version": "0.4.4", + "id": "registry+https://github.com/rust-lang/crates.io-index#cipher@0.4.4", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cipher-0.4.4/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "crypto", + "block-cipher", + "stream-cipher", + "trait" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/traits", + "homepage": null, + "documentation": "https://docs.rs/cipher", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.56" + }, + { + "name": "clap", + "version": "4.6.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#clap@4.6.1", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap-4.6.1/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "unstable-doc" + ], + "rustdoc-args": [ + "--generate-link-to-definition" + ] + } + }, + "playground": { + "features": [ + "unstable-doc" + ] + }, + "release": { + "shared-version": true, + "tag-name": "v{{version}}", + "pre-release-replacements": [ + { + "file": "CHANGELOG.md", + "search": "Unreleased", + "replace": "{{version}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "\\.\\.\\.HEAD", + "replace": "...{{tag_name}}", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "ReleaseDate", + "replace": "{{date}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n## [Unreleased] - ReleaseDate\n", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n[Unreleased]: https://github.com/clap-rs/clap/compare/{{tag_name}}...HEAD", + "exactly": 1 + }, + { + "file": "CITATION.cff", + "search": "^date-released: ....-..-..", + "replace": "date-released: {{date}}" + }, + { + "file": "CITATION.cff", + "search": "^version: .+\\..+\\..+", + "replace": "version: {{version}}" + }, + { + "file": "src/lib.rs", + "search": "blob/v.+\\..+\\..+/CHANGELOG.md", + "replace": "blob/v{{version}}/CHANGELOG.md", + "exactly": 1 + } + ] + } + }, + "publish": null, + "authors": [], + "categories": [ + "command-line-interface" + ], + "keywords": [ + "argument", + "cli", + "arg", + "parser", + "parse" + ], + "readme": null, + "repository": "https://github.com/clap-rs/clap", + "homepage": null, + "documentation": null, + "edition": "2024", + "links": null, + "default_run": null, + "rust_version": "1.85" + }, + { + "name": "clap_builder", + "version": "4.6.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#clap_builder@4.6.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_builder-4.6.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "unstable-doc" + ], + "rustdoc-args": [ + "--generate-link-to-definition" + ] + } + }, + "playground": { + "features": [ + "unstable-doc" + ] + }, + "release": { + "shared-version": true, + "dependent-version": "upgrade", + "tag-name": "v{{version}}" + } + }, + "publish": null, + "authors": [], + "categories": [ + "command-line-interface" + ], + "keywords": [ + "argument", + "cli", + "arg", + "parser", + "parse" + ], + "readme": null, + "repository": "https://github.com/clap-rs/clap", + "homepage": null, + "documentation": null, + "edition": "2024", + "links": null, + "default_run": null, + "rust_version": "1.85" + }, + { + "name": "clap_derive", + "version": "4.6.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#clap_derive@4.6.1", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_derive-4.6.1/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition" + ] + } + }, + "release": { + "shared-version": true, + "dependent-version": "upgrade", + "tag-name": "v{{version}}" + } + }, + "publish": null, + "authors": [], + "categories": [ + "command-line-interface", + "development-tools::procedural-macro-helpers" + ], + "keywords": [ + "clap", + "cli", + "parse", + "derive", + "proc_macro" + ], + "readme": null, + "repository": "https://github.com/clap-rs/clap", + "homepage": null, + "documentation": null, + "edition": "2024", + "links": null, + "default_run": null, + "rust_version": "1.85" + }, + { + "name": "clap_lex", + "version": "1.1.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#clap_lex@1.1.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_lex-1.1.0/Cargo.toml", + "metadata": { + "release": { + "pre-release-replacements": [ + { + "file": "CHANGELOG.md", + "search": "Unreleased", + "replace": "{{version}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "\\.\\.\\.HEAD", + "replace": "...{{tag_name}}", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "ReleaseDate", + "replace": "{{date}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n## [Unreleased] - ReleaseDate\n", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n[Unreleased]: https://github.com/clap-rs/clap/compare/{{tag_name}}...HEAD", + "exactly": 1 + }, + { + "file": "README.md", + "search": "github.com/clap-rs/clap/blob/[^/]+/", + "replace": "github.com/clap-rs/clap/blob/{{tag_name}}/", + "exactly": 4, + "prerelease": true + } + ] + } + }, + "publish": null, + "authors": [], + "categories": [ + "command-line-interface" + ], + "keywords": [ + "argument", + "cli", + "arg", + "parser", + "parse" + ], + "readme": null, + "repository": "https://github.com/clap-rs/clap", + "homepage": null, + "documentation": null, + "edition": "2024", + "links": null, + "default_run": null, + "rust_version": "1.85" + }, + { + "name": "cmake", + "version": "0.1.58", + "id": "registry+https://github.com/rust-lang/crates.io-index#cmake@0.1.58", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cmake-0.1.58/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Alex Crichton " + ], + "categories": [ + "development-tools::build-utils" + ], + "keywords": [ + "build-dependencies" + ], + "readme": null, + "repository": "https://github.com/rust-lang/cmake-rs", + "homepage": "https://github.com/rust-lang/cmake-rs", + "documentation": "https://docs.rs/cmake", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.65" + }, + { + "name": "colorchoice", + "version": "1.0.5", + "id": "registry+https://github.com/rust-lang/crates.io-index#colorchoice@1.0.5", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/colorchoice-1.0.5/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs", + "--generate-link-to-definition" + ] + } + }, + "release": { + "pre-release-replacements": [ + { + "file": "CHANGELOG.md", + "search": "Unreleased", + "replace": "{{version}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "\\.\\.\\.HEAD", + "replace": "...{{tag_name}}", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "ReleaseDate", + "replace": "{{date}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n## [Unreleased] - ReleaseDate\n", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n[Unreleased]: https://github.com/rust-cli/anstyle/compare/{{tag_name}}...HEAD", + "exactly": 1 + } + ] + } + }, + "publish": null, + "authors": [], + "categories": [ + "command-line-interface" + ], + "keywords": [ + "cli", + "color", + "no-std", + "terminal", + "ansi" + ], + "readme": null, + "repository": "https://github.com/rust-cli/anstyle.git", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.66.0" + }, + { + "name": "const-oid", + "version": "0.9.6", + "id": "registry+https://github.com/rust-lang/crates.io-index#const-oid@0.9.6", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/const-oid-0.9.6/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "data-structures", + "encoding", + "no-std", + "parser-implementations" + ], + "keywords": [ + "iso", + "iec", + "itu", + "oid" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/formats/tree/master/const-oid", + "homepage": null, + "documentation": "https://docs.rs/const-oid", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.57" + }, + { + "name": "cpufeatures", + "version": "0.2.17", + "id": "registry+https://github.com/rust-lang/crates.io-index#cpufeatures@0.2.17", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cpufeatures-0.2.17/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "hardware-support", + "no-std" + ], + "keywords": [ + "cpuid", + "target-feature" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/utils", + "homepage": null, + "documentation": "https://docs.rs/cpufeatures", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "crypto-common", + "version": "0.1.7", + "id": "registry+https://github.com/rust-lang/crates.io-index#crypto-common@0.1.7", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-common-0.1.7/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "crypto", + "traits" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/traits", + "homepage": null, + "documentation": "https://docs.rs/crypto-common", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "der", + "version": "0.7.10", + "id": "registry+https://github.com/rust-lang/crates.io-index#der@0.7.10", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/der-0.7.10/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "data-structures", + "encoding", + "no-std", + "parser-implementations" + ], + "keywords": [ + "asn1", + "crypto", + "itu", + "pkcs" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/formats/tree/master/der", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.65" + }, + { + "name": "digest", + "version": "0.10.7", + "id": "registry+https://github.com/rust-lang/crates.io-index#digest@0.10.7", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "digest", + "crypto", + "hash" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/traits", + "homepage": null, + "documentation": "https://docs.rs/digest", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "dnp3", + "version": "1.7.0", + "id": "path+file:///build/dnp3/dnp3#1.7.0", + "license": null, + "license_file": "../LICENSE.txt", + "description": null, + "source": null, + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/build/dnp3/dnp3/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Step Function I/O LLC " + ], + "categories": [ + "network-programming" + ], + "keywords": [ + "dnp3", + "ics", + "scada", + "security" + ], + "readme": null, + "repository": "https://github.com/stepfunc/dnp3", + "homepage": "https://stepfunc.io/products/libraries/dnp3/", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.75" + }, + { + "name": "dnp3-bindings", + "version": "1.7.0", + "id": "path+file:///build/dnp3/ffi/dnp3-bindings#1.7.0", + "license": null, + "license_file": "../../LICENSE.txt", + "description": null, + "source": null, + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/build/dnp3/ffi/dnp3-bindings/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [ + "network-programming" + ], + "keywords": [ + "dnp3", + "ics", + "scada", + "security" + ], + "readme": null, + "repository": "https://github.com/stepfunc/dnp3", + "homepage": "https://stepfunc.io/products/libraries/dnp3/", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.75" + }, + { + "name": "dnp3-cli-utils", + "version": "0.1.0", + "id": "path+file:///build/dnp3/examples/cli-utils#dnp3-cli-utils@0.1.0", + "license": null, + "license_file": "../../LICENSE.txt", + "description": null, + "source": null, + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/build/dnp3/examples/cli-utils/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Step Function I/O LLC " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "dnp3-ffi", + "version": "1.7.0", + "id": "path+file:///build/dnp3/ffi/dnp3-ffi#1.7.0", + "license": null, + "license_file": "../../LICENSE.txt", + "description": null, + "source": null, + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/build/dnp3/ffi/dnp3-ffi/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [ + "network-programming" + ], + "keywords": [ + "dnp3", + "ics", + "scada", + "security" + ], + "readme": null, + "repository": "https://github.com/stepfunc/dnp3", + "homepage": "https://stepfunc.io/products/libraries/dnp3/", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.75" + }, + { + "name": "dnp3-ffi-java", + "version": "1.7.0", + "id": "path+file:///build/dnp3/ffi/dnp3-ffi-java#1.7.0", + "license": null, + "license_file": "../../LICENSE.txt", + "description": null, + "source": null, + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/build/dnp3/ffi/dnp3-ffi-java/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [ + "network-programming" + ], + "keywords": [ + "dnp3", + "ics", + "scada", + "security" + ], + "readme": null, + "repository": "https://github.com/stepfunc/dnp3", + "homepage": "https://stepfunc.io/products/libraries/dnp3/", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.75" + }, + { + "name": "dnp3-schema", + "version": "1.7.0", + "id": "path+file:///build/dnp3/ffi/dnp3-schema#1.7.0", + "license": null, + "license_file": "../../LICENSE.txt", + "description": null, + "source": null, + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/build/dnp3/ffi/dnp3-schema/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [ + "network-programming" + ], + "keywords": [ + "dnp3", + "ics", + "scada", + "security" + ], + "readme": null, + "repository": "https://github.com/stepfunc/dnp3", + "homepage": "https://stepfunc.io/products/libraries/dnp3/", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.75" + }, + { + "name": "dunce", + "version": "1.0.5", + "id": "registry+https://github.com/rust-lang/crates.io-index#dunce@1.0.5", + "license": "CC0-1.0 OR MIT-0 OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/dunce-1.0.5/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "rustdoc-args": [ + "--generate-link-to-definition" + ], + "targets": [ + "x86_64-unknown-linux-gnu" + ] + } + } + }, + "publish": null, + "authors": [ + "Kornel " + ], + "categories": [ + "filesystem" + ], + "keywords": [ + "realpath", + "unc", + "canonicalize", + "windows", + "deunc" + ], + "readme": null, + "repository": "https://gitlab.com/kornelski/dunce", + "homepage": "https://lib.rs/crates/dunce", + "documentation": "https://docs.rs/dunce", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "example-master", + "version": "0.1.0", + "id": "path+file:///build/dnp3/examples/master#example-master@0.1.0", + "license": null, + "license_file": "../../LICENSE.txt", + "description": null, + "source": null, + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/build/dnp3/examples/master/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Step Function I/O LLC " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "example-master-tcp-server", + "version": "0.1.0", + "id": "path+file:///build/dnp3/examples/master_tcp_server#example-master-tcp-server@0.1.0", + "license": null, + "license_file": "../../LICENSE.txt", + "description": null, + "source": null, + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/build/dnp3/examples/master_tcp_server/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Step Function I/O LLC " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "example-outstation", + "version": "0.1.0", + "id": "path+file:///build/dnp3/examples/outstation#example-outstation@0.1.0", + "license": null, + "license_file": "../../LICENSE.txt", + "description": null, + "source": null, + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/build/dnp3/examples/outstation/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Step Function I/O LLC " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "find-msvc-tools", + "version": "0.1.9", + "id": "registry+https://github.com/rust-lang/crates.io-index#find-msvc-tools@0.1.9", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/find-msvc-tools-0.1.9/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [ + "development-tools::build-utils" + ], + "keywords": [ + "build-dependencies" + ], + "readme": null, + "repository": "https://github.com/rust-lang/cc-rs", + "homepage": null, + "documentation": "https://docs.rs/find-msvc-tools", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.63" + }, + { + "name": "fs_extra", + "version": "1.3.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#fs_extra@1.3.0", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/fs_extra-1.3.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Denis Kurilenko " + ], + "categories": [], + "keywords": [ + "filesystem", + "recursion", + "copy", + "dir", + "file" + ], + "readme": null, + "repository": "https://github.com/webdesus/fs_extra", + "homepage": "https://github.com/webdesus/fs_extra", + "documentation": "https://docs.rs/fs_extra", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "futures", + "version": "0.3.32", + "id": "registry+https://github.com/rust-lang/crates.io-index#futures@0.3.32", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-0.3.32/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + }, + "playground": { + "features": [ + "std", + "async-await", + "compat", + "io-compat", + "executor", + "thread-pool" + ] + } + }, + "publish": null, + "authors": [], + "categories": [ + "asynchronous" + ], + "keywords": [ + "futures", + "async", + "future" + ], + "readme": null, + "repository": "https://github.com/rust-lang/futures-rs", + "homepage": "https://rust-lang.github.io/futures-rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "futures-channel", + "version": "0.3.32", + "id": "registry+https://github.com/rust-lang/crates.io-index#futures-channel@0.3.32", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-channel-0.3.32/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/futures-rs", + "homepage": "https://rust-lang.github.io/futures-rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "futures-core", + "version": "0.3.32", + "id": "registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.32", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-core-0.3.32/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/futures-rs", + "homepage": "https://rust-lang.github.io/futures-rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.36" + }, + { + "name": "futures-executor", + "version": "0.3.32", + "id": "registry+https://github.com/rust-lang/crates.io-index#futures-executor@0.3.32", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-executor-0.3.32/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/futures-rs", + "homepage": "https://rust-lang.github.io/futures-rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "futures-io", + "version": "0.3.32", + "id": "registry+https://github.com/rust-lang/crates.io-index#futures-io@0.3.32", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-io-0.3.32/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/futures-rs", + "homepage": "https://rust-lang.github.io/futures-rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.36" + }, + { + "name": "futures-macro", + "version": "0.3.32", + "id": "registry+https://github.com/rust-lang/crates.io-index#futures-macro@0.3.32", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-macro-0.3.32/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/futures-rs", + "homepage": "https://rust-lang.github.io/futures-rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "futures-sink", + "version": "0.3.32", + "id": "registry+https://github.com/rust-lang/crates.io-index#futures-sink@0.3.32", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-sink-0.3.32/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true + } + } + }, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/futures-rs", + "homepage": "https://rust-lang.github.io/futures-rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.36" + }, + { + "name": "futures-task", + "version": "0.3.32", + "id": "registry+https://github.com/rust-lang/crates.io-index#futures-task@0.3.32", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-task-0.3.32/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true + } + } + }, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/futures-rs", + "homepage": "https://rust-lang.github.io/futures-rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "futures-util", + "version": "0.3.32", + "id": "registry+https://github.com/rust-lang/crates.io-index#futures-util@0.3.32", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-util-0.3.32/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/futures-rs", + "homepage": "https://rust-lang.github.io/futures-rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "generic-array", + "version": "0.14.7", + "id": "registry+https://github.com/rust-lang/crates.io-index#generic-array@0.14.7", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "serde", + "zeroize" + ] + } + } + }, + "publish": null, + "authors": [ + "Bart\u0142omiej Kami\u0144ski ", + "Aaron Trent " + ], + "categories": [ + "data-structures", + "no-std" + ], + "keywords": [ + "generic", + "array" + ], + "readme": null, + "repository": "https://github.com/fizyk20/generic-array.git", + "homepage": null, + "documentation": "http://fizyk20.github.io/generic-array/generic_array/", + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "getrandom", + "version": "0.2.17", + "id": "registry+https://github.com/rust-lang/crates.io-index#getrandom@0.2.17", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/getrandom-0.2.17/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "std", + "custom" + ], + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + }, + "cross": { + "target": { + "x86_64-unknown-netbsd": { + "pre-build": [ + "mkdir -p /tmp/netbsd", + "curl https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.2/amd64/binary/sets/base.tar.xz -O", + "tar -C /tmp/netbsd -xJf base.tar.xz", + "cp /tmp/netbsd/usr/lib/libexecinfo.so /usr/local/x86_64-unknown-netbsd/lib", + "rm base.tar.xz", + "rm -rf /tmp/netbsd" + ] + } + } + } + }, + "publish": null, + "authors": [ + "The Rand Project Developers" + ], + "categories": [ + "os", + "no-std" + ], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-random/getrandom", + "homepage": null, + "documentation": "https://docs.rs/getrandom", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "gimli", + "version": "0.32.3", + "id": "registry+https://github.com/rust-lang/crates.io-index#gimli@0.32.3", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/gimli-0.32.3/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [ + "development-tools::debugging", + "development-tools::profiling", + "parser-implementations" + ], + "keywords": [ + "DWARF", + "debug", + "ELF", + "eh_frame" + ], + "readme": null, + "repository": "https://github.com/gimli-rs/gimli", + "homepage": null, + "documentation": "https://docs.rs/gimli", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.60" + }, + { + "name": "heck", + "version": "0.5.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#heck@0.5.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/heck-0.5.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [ + "no-std" + ], + "keywords": [ + "string", + "case", + "camel", + "snake", + "unicode" + ], + "readme": null, + "repository": "https://github.com/withoutboats/heck", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.56" + }, + { + "name": "hmac", + "version": "0.12.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#hmac@0.12.1", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hmac-0.12.1/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "crypto", + "mac", + "hmac", + "digest" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/MACs", + "homepage": null, + "documentation": "https://docs.rs/hmac", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "iana-time-zone", + "version": "0.1.65", + "id": "registry+https://github.com/rust-lang/crates.io-index#iana-time-zone@0.1.65", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iana-time-zone-0.1.65/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Andrew Straw ", + "Ren\u00e9 Kijewski ", + "Ryan Lopopolo " + ], + "categories": [ + "date-and-time", + "internationalization", + "os" + ], + "keywords": [ + "IANA", + "time" + ], + "readme": null, + "repository": "https://github.com/strawlab/iana-time-zone", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.62.0" + }, + { + "name": "inout", + "version": "0.1.4", + "id": "registry+https://github.com/rust-lang/crates.io-index#inout@0.1.4", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/inout-0.1.4/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [], + "keywords": [ + "custom-reference" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/utils", + "homepage": null, + "documentation": "https://docs.rs/inout", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.56" + }, + { + "name": "is_terminal_polyfill", + "version": "1.70.2", + "id": "registry+https://github.com/rust-lang/crates.io-index#is_terminal_polyfill@1.70.2", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/is_terminal_polyfill-1.70.2/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true + } + }, + "release": { + "pre-release-replacements": [ + { + "file": "CHANGELOG.md", + "search": "Unreleased", + "replace": "{{version}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "\\.\\.\\.HEAD", + "replace": "...{{tag_name}}", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "ReleaseDate", + "replace": "{{date}}", + "min": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n## [Unreleased] - ReleaseDate\n", + "exactly": 1 + }, + { + "file": "CHANGELOG.md", + "search": "", + "replace": "\n[Unreleased]: https://github.com/polyfill-rs/is_terminal_polyfill/compare/{{tag_name}}...HEAD", + "exactly": 1 + } + ] + } + }, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/polyfill-rs/is_terminal_polyfill", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.70.0" + }, + { + "name": "itoa", + "version": "1.0.18", + "id": "registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.18", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/itoa-1.0.18/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org" + ] + } + } + }, + "publish": null, + "authors": [ + "David Tolnay " + ], + "categories": [ + "value-formatting", + "no-std", + "no-std::no-alloc" + ], + "keywords": [ + "integer" + ], + "readme": null, + "repository": "https://github.com/dtolnay/itoa", + "homepage": null, + "documentation": "https://docs.rs/itoa", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.68" + }, + { + "name": "jobserver", + "version": "0.1.34", + "id": "registry+https://github.com/rust-lang/crates.io-index#jobserver@0.1.34", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/jobserver-0.1.34/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Alex Crichton " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/jobserver-rs", + "homepage": "https://github.com/rust-lang/jobserver-rs", + "documentation": "https://docs.rs/jobserver", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.63" + }, + { + "name": "lazy_static", + "version": "1.5.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#lazy_static@1.5.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lazy_static-1.5.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Marvin L\u00f6bel " + ], + "categories": [ + "no-std", + "rust-patterns", + "memory-management" + ], + "keywords": [ + "macro", + "lazy", + "static" + ], + "readme": null, + "repository": "https://github.com/rust-lang-nursery/lazy-static.rs", + "homepage": null, + "documentation": "https://docs.rs/lazy_static", + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "libc", + "version": "0.2.185", + "id": "registry+https://github.com/rust-lang/crates.io-index#libc@0.2.185", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "extra_traits" + ], + "default-target": "x86_64-unknown-linux-gnu", + "targets": [ + "aarch64-apple-darwin", + "aarch64-pc-windows-msvc", + "aarch64-unknown-linux-gnu", + "i686-pc-windows-msvc", + "i686-unknown-linux-gnu", + "x86_64-pc-windows-gnu", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu", + "aarch64-pc-windows-gnullvm", + "aarch64-unknown-linux-musl", + "aarch64-unknown-linux-ohos", + "arm-unknown-linux-gnueabi", + "arm-unknown-linux-gnueabihf", + "armv7-unknown-linux-gnueabihf", + "armv7-unknown-linux-ohos", + "i686-pc-windows-gnu", + "loongarch64-unknown-linux-gnu", + "loongarch64-unknown-linux-musl", + "powerpc-unknown-linux-gnu", + "powerpc64-unknown-linux-gnu", + "powerpc64le-unknown-linux-gnu", + "powerpc64le-unknown-linux-musl", + "riscv64gc-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "sparcv9-sun-solaris", + "x86_64-apple-darwin", + "x86_64-pc-solaris", + "x86_64-pc-windows-gnullvm", + "x86_64-unknown-freebsd", + "x86_64-unknown-illumos", + "x86_64-unknown-linux-musl", + "x86_64-unknown-linux-ohos", + "x86_64-unknown-netbsd", + "aarch64-apple-ios", + "aarch64-apple-tvos", + "aarch64-apple-visionos", + "aarch64-apple-watchos", + "aarch64-linux-android", + "aarch64-unknown-fuchsia", + "arm-linux-androideabi", + "arm-unknown-linux-musleabi", + "arm-unknown-linux-musleabihf", + "arm64ec-pc-windows-msvc", + "armv5te-unknown-linux-gnueabi", + "armv5te-unknown-linux-musleabi", + "armv7-linux-androideabi", + "armv7-unknown-linux-musleabihf", + "i586-unknown-linux-gnu", + "i586-unknown-linux-musl", + "i686-linux-android", + "i686-unknown-freebsd", + "i686-unknown-linux-musl", + "nvptx64-nvidia-cuda", + "riscv64gc-unknown-linux-musl", + "sparc64-unknown-linux-gnu", + "thumbv7neon-linux-androideabi", + "thumbv7neon-unknown-linux-gnueabihf", + "wasm32-unknown-emscripten", + "wasm32-unknown-unknown", + "wasm32-wasip1", + "wasm32-wasip2", + "x86_64-fortanix-unknown-sgx", + "x86_64-linux-android", + "x86_64-unknown-fuchsia", + "x86_64-unknown-linux-gnux32", + "x86_64-unknown-redox", + "aarch64-unknown-freebsd", + "aarch64-unknown-hermit", + "aarch64-unknown-illumos", + "aarch64-unknown-netbsd", + "aarch64-unknown-nto-qnx800", + "aarch64-unknown-openbsd", + "aarch64-unknown-redox", + "aarch64-wrs-vxworks", + "aarch64_be-unknown-linux-gnu", + "aarch64_be-unknown-linux-musl", + "armebv7r-none-eabi", + "armebv7r-none-eabihf", + "armv7-linux-androideabi", + "armv7-wrs-vxworks-eabihf", + "armv7r-none-eabi", + "armv7r-none-eabihf", + "hexagon-unknown-linux-musl", + "i686-unknown-haiku", + "i686-unknown-netbsd", + "i686-unknown-openbsd", + "i686-wrs-vxworks", + "mips-unknown-linux-gnu", + "mips-unknown-linux-musl", + "mips64-unknown-linux-gnuabi64", + "mips64-unknown-linux-muslabi64", + "mips64el-unknown-linux-gnuabi64", + "mips64el-unknown-linux-muslabi64", + "mipsel-sony-psp", + "mipsel-unknown-linux-gnu", + "mipsel-unknown-linux-musl", + "powerpc-unknown-linux-gnuspe", + "powerpc-unknown-netbsd", + "powerpc-wrs-vxworks", + "powerpc-wrs-vxworks-spe", + "powerpc64-ibm-aix", + "powerpc64-unknown-freebsd", + "powerpc64-unknown-linux-gnu", + "powerpc64-unknown-linux-musl", + "powerpc64-wrs-vxworks", + "riscv32-wrs-vxworks", + "riscv32gc-unknown-linux-musl", + "riscv32i-unknown-none-elf", + "riscv32imac-unknown-none-elf", + "riscv32imc-unknown-none-elf", + "riscv64-wrs-vxworks", + "riscv64gc-unknown-freebsd", + "riscv64gc-unknown-hermit", + "riscv64gc-unknown-none-elf", + "riscv64imac-unknown-none-elf", + "s390x-unknown-linux-musl", + "sparc-unknown-linux-gnu", + "sparc64-unknown-netbsd", + "thumbv6m-none-eabi", + "thumbv7em-none-eabi", + "thumbv7em-none-eabihf", + "thumbv7m-none-eabi", + "wasm32-wasip3", + "x86_64-apple-ios", + "x86_64-pc-cygwin", + "x86_64-unknown-dragonfly", + "x86_64-unknown-haiku", + "x86_64-unknown-hermit", + "x86_64-unknown-hurd-gnu", + "x86_64-unknown-l4re-uclibc", + "x86_64-unknown-openbsd", + "x86_64-wrs-vxworks" + ], + "cargo-args": [ + "-Zbuild-std=core" + ] + } + }, + "cargo-semver-checks": { + "lints": { + "repr_align_removed": "warn", + "global_value_marked_deprecated": "warn" + } + } + }, + "publish": null, + "authors": [ + "The Rust Project Developers" + ], + "categories": [ + "external-ffi-bindings", + "no-std", + "os" + ], + "keywords": [ + "libc", + "ffi", + "bindings", + "operating", + "system" + ], + "readme": null, + "repository": "https://github.com/rust-lang/libc", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.65" + }, + { + "name": "log", + "version": "0.4.29", + "id": "registry+https://github.com/rust-lang/crates.io-index#log@0.4.29", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/log-0.4.29/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "std", + "serde", + "kv_std", + "kv_sval", + "kv_serde" + ] + } + } + }, + "publish": null, + "authors": [ + "The Rust Project Developers" + ], + "categories": [ + "development-tools::debugging" + ], + "keywords": [ + "logging" + ], + "readme": null, + "repository": "https://github.com/rust-lang/log", + "homepage": null, + "documentation": "https://docs.rs/log", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.68.0" + }, + { + "name": "memchr", + "version": "2.8.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.0", + "license": "Unlicense OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/memchr-2.8.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "rustdoc-args": [ + "--generate-link-to-definition" + ] + } + } + }, + "publish": null, + "authors": [ + "Andrew Gallant ", + "bluss" + ], + "categories": [], + "keywords": [ + "memchr", + "memmem", + "substring", + "find", + "search" + ], + "readme": null, + "repository": "https://github.com/BurntSushi/memchr", + "homepage": "https://github.com/BurntSushi/memchr", + "documentation": "https://docs.rs/memchr/", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.61" + }, + { + "name": "miniz_oxide", + "version": "0.8.9", + "id": "registry+https://github.com/rust-lang/crates.io-index#miniz_oxide@0.8.9", + "license": "MIT OR Zlib OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/miniz_oxide-0.8.9/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Frommi ", + "oyvindln ", + "Rich Geldreich richgel99@gmail.com" + ], + "categories": [ + "compression" + ], + "keywords": [ + "zlib", + "miniz", + "deflate", + "encoding" + ], + "readme": null, + "repository": "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide", + "homepage": "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide", + "documentation": "https://docs.rs/miniz_oxide", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "mio", + "version": "1.2.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#mio@1.2.0", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/mio-1.2.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs", + "--generate-link-to-definition" + ], + "targets": [ + "aarch64-apple-ios", + "aarch64-linux-android", + "wasm32-wasip1", + "x86_64-apple-darwin", + "x86_64-pc-windows-gnu", + "x86_64-pc-windows-msvc", + "x86_64-unknown-dragonfly", + "x86_64-unknown-freebsd", + "x86_64-unknown-illumos", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-netbsd", + "x86_64-unknown-openbsd", + "x86_64-unknown-hermit" + ] + } + }, + "playground": { + "features": [ + "os-poll", + "os-ext", + "net" + ] + } + }, + "publish": null, + "authors": [ + "Carl Lerche ", + "Thomas de Zeeuw ", + "Tokio Contributors " + ], + "categories": [ + "asynchronous" + ], + "keywords": [ + "io", + "async", + "non-blocking" + ], + "readme": null, + "repository": "https://github.com/tokio-rs/mio", + "homepage": "https://github.com/tokio-rs/mio", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "mio-serial", + "version": "5.0.6", + "id": "registry+https://github.com/rust-lang/crates.io-index#mio-serial@5.0.6", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/mio-serial-5.0.6/Cargo.toml", + "metadata": { + "msrv": "1.78.0" + }, + "publish": null, + "authors": [ + "Zac Berkowitz " + ], + "categories": [ + "asynchronous", + "hardware-support" + ], + "keywords": [ + "rs232", + "serial", + "mio" + ], + "readme": null, + "repository": "https://github.com/berkowski/mio-serial", + "homepage": "https://github.com/berkowski/mio-serial", + "documentation": "https://docs.rs/mio-serial", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "nix", + "version": "0.26.4", + "id": "registry+https://github.com/rust-lang/crates.io-index#nix@0.26.4", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.26.4/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "rustdoc-args": [ + "--cfg", + "docsrs" + ], + "targets": [ + "x86_64-unknown-linux-gnu", + "aarch64-linux-android", + "x86_64-apple-darwin", + "aarch64-apple-ios", + "x86_64-unknown-freebsd", + "x86_64-unknown-openbsd", + "x86_64-unknown-netbsd", + "x86_64-unknown-dragonfly", + "x86_64-fuchsia", + "x86_64-unknown-redox", + "x86_64-unknown-illumos" + ] + } + } + }, + "publish": null, + "authors": [ + "The nix-rust Project Developers" + ], + "categories": [ + "os::unix-apis" + ], + "keywords": [], + "readme": null, + "repository": "https://github.com/nix-rust/nix", + "homepage": null, + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.56" + }, + { + "name": "nix", + "version": "0.29.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#nix@0.29.0", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.29.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ], + "targets": [ + "x86_64-unknown-linux-gnu", + "aarch64-linux-android", + "x86_64-apple-darwin", + "aarch64-apple-ios", + "x86_64-unknown-freebsd", + "x86_64-unknown-openbsd", + "x86_64-unknown-netbsd", + "x86_64-unknown-dragonfly", + "x86_64-fuchsia", + "x86_64-unknown-redox", + "x86_64-unknown-illumos" + ] + } + } + }, + "publish": null, + "authors": [ + "The nix-rust Project Developers" + ], + "categories": [ + "os::unix-apis" + ], + "keywords": [], + "readme": null, + "repository": "https://github.com/nix-rust/nix", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.69" + }, + { + "name": "nu-ansi-term", + "version": "0.50.3", + "id": "registry+https://github.com/rust-lang/crates.io-index#nu-ansi-term@0.50.3", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nu-ansi-term-0.50.3/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "ogham@bsago.me", + "Ryan Scheel (Havvy) ", + "Josh Triplett ", + "The Nushell Project Developers" + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/nushell/nu-ansi-term", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.62.1" + }, + { + "name": "num-traits", + "version": "0.2.19", + "id": "registry+https://github.com/rust-lang/crates.io-index#num-traits@0.2.19", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "std" + ], + "rustdoc-args": [ + "--generate-link-to-definition" + ] + } + } + }, + "publish": null, + "authors": [ + "The Rust Project Developers" + ], + "categories": [ + "algorithms", + "science", + "no-std" + ], + "keywords": [ + "mathematics", + "numerics" + ], + "readme": null, + "repository": "https://github.com/rust-num/num-traits", + "homepage": "https://github.com/rust-num/num-traits", + "documentation": "https://docs.rs/num-traits", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.60" + }, + { + "name": "num_cpus", + "version": "1.17.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#num_cpus@1.17.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num_cpus-1.17.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Sean McArthur " + ], + "categories": [ + "hardware-support" + ], + "keywords": [ + "cpu", + "cpus", + "cores" + ], + "readme": null, + "repository": "https://github.com/seanmonstar/num_cpus", + "homepage": null, + "documentation": "https://docs.rs/num_cpus", + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "object", + "version": "0.37.3", + "id": "registry+https://github.com/rust-lang/crates.io-index#object@0.37.3", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/object-0.37.3/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "doc" + ] + } + } + }, + "publish": null, + "authors": [], + "categories": [], + "keywords": [ + "object", + "elf", + "mach-o", + "pe", + "coff" + ], + "readme": null, + "repository": "https://github.com/gimli-rs/object", + "homepage": null, + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.65" + }, + { + "name": "once_cell", + "version": "1.21.4", + "id": "registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.4", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/once_cell-1.21.4/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--generate-link-to-definition" + ] + } + } + }, + "publish": null, + "authors": [ + "Aleksey Kladov " + ], + "categories": [ + "rust-patterns", + "memory-management" + ], + "keywords": [ + "lazy", + "static" + ], + "readme": null, + "repository": "https://github.com/matklad/once_cell", + "homepage": null, + "documentation": "https://docs.rs/once_cell", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.65" + }, + { + "name": "oo-bindgen", + "version": "0.8.8", + "id": "registry+https://github.com/rust-lang/crates.io-index#oo-bindgen@0.8.8", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/oo-bindgen-0.8.8/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Step Function I/O LLC " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/stepfunc/oo_bindgen/", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "pbkdf2", + "version": "0.12.2", + "id": "registry+https://github.com/rust-lang/crates.io-index#pbkdf2@0.12.2", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pbkdf2-0.12.2/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "authentication", + "cryptography", + "no-std" + ], + "keywords": [ + "crypto", + "hashing", + "password", + "phf" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/password-hashes/tree/master/pbkdf2", + "homepage": null, + "documentation": "https://docs.rs/pbkdf2", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.60" + }, + { + "name": "pem", + "version": "3.0.6", + "id": "registry+https://github.com/rust-lang/crates.io-index#pem@3.0.6", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pem-3.0.6/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Jonathan Creekmore " + ], + "categories": [ + "cryptography" + ], + "keywords": [ + "no-std", + "no_std", + "pem" + ], + "readme": null, + "repository": "https://github.com/jcreekmore/pem-rs.git", + "homepage": "https://github.com/jcreekmore/pem-rs.git", + "documentation": "https://docs.rs/pem/", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.60.0" + }, + { + "name": "pem-rfc7468", + "version": "0.7.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#pem-rfc7468@0.7.0", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pem-rfc7468-0.7.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "data-structures", + "encoding", + "no-std", + "parser-implementations" + ], + "keywords": [ + "crypto", + "key", + "pem", + "pkcs", + "rsa" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/formats/tree/master/pem-rfc7468", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.60" + }, + { + "name": "perf-tests", + "version": "0.1.0", + "id": "path+file:///build/dnp3/examples/perf#perf-tests@0.1.0", + "license": null, + "license_file": "../../LICENSE.txt", + "description": null, + "source": null, + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/build/dnp3/examples/perf/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Step Function I/O LLC " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "pin-project-lite", + "version": "0.2.17", + "id": "registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.17", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pin-project-lite-0.2.17/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "targets": [ + "x86_64-unknown-linux-gnu" + ] + } + }, + "cargo_check_external_types": { + "allowed_external_types": [] + } + }, + "publish": null, + "authors": [], + "categories": [ + "no-std", + "no-std::no-alloc", + "rust-patterns" + ], + "keywords": [ + "pin", + "macros" + ], + "readme": null, + "repository": "https://github.com/taiki-e/pin-project-lite", + "homepage": null, + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.37" + }, + { + "name": "pkcs5", + "version": "0.7.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#pkcs5@0.7.1", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkcs5-0.7.1/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "data-structures", + "encoding", + "no-std" + ], + "keywords": [ + "crypto", + "key", + "pkcs", + "password" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/formats/tree/master/pkcs5", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.65" + }, + { + "name": "pkcs8", + "version": "0.10.2", + "id": "registry+https://github.com/rust-lang/crates.io-index#pkcs8@0.10.2", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkcs8-0.10.2/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "data-structures", + "encoding", + "no-std", + "parser-implementations" + ], + "keywords": [ + "crypto", + "key", + "pkcs", + "private" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/formats/tree/master/pkcs8", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.65" + }, + { + "name": "pkg-config", + "version": "0.3.34", + "id": "registry+https://github.com/rust-lang/crates.io-index#pkg-config@0.3.34", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkg-config-0.3.34/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Alex Crichton " + ], + "categories": [], + "keywords": [ + "build-dependencies" + ], + "readme": null, + "repository": "https://github.com/rust-lang/pkg-config-rs", + "homepage": null, + "documentation": "https://docs.rs/pkg-config", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.63" + }, + { + "name": "platforms", + "version": "2.0.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#platforms@2.0.0", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/platforms-2.0.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Tony Arcieri " + ], + "categories": [ + "development-tools", + "no-std" + ], + "keywords": [ + "architectures", + "cpu", + "platforms", + "os", + "targets" + ], + "readme": null, + "repository": "https://github.com/rustsec/rustsec/tree/main/platforms", + "homepage": "https://rustsec.org", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "proc-macro2", + "version": "1.0.106", + "id": "registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/proc-macro2-1.0.106/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "rustc-args": [ + "--cfg=procmacro2_semver_exempt" + ], + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--cfg=procmacro2_semver_exempt", + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org" + ] + } + }, + "playground": { + "features": [ + "span-locations" + ] + } + }, + "publish": null, + "authors": [ + "David Tolnay ", + "Alex Crichton " + ], + "categories": [ + "development-tools::procedural-macro-helpers" + ], + "keywords": [ + "macros", + "syn" + ], + "readme": null, + "repository": "https://github.com/dtolnay/proc-macro2", + "homepage": null, + "documentation": "https://docs.rs/proc-macro2", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.68" + }, + { + "name": "quote", + "version": "1.0.45", + "id": "registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.45/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org" + ] + } + } + }, + "publish": null, + "authors": [ + "David Tolnay " + ], + "categories": [ + "development-tools::procedural-macro-helpers" + ], + "keywords": [ + "macros", + "syn" + ], + "readme": null, + "repository": "https://github.com/dtolnay/quote", + "homepage": null, + "documentation": "https://docs.rs/quote/", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "rand_core", + "version": "0.6.4", + "id": "registry+https://github.com/rust-lang/crates.io-index#rand_core@0.6.4", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rand_core-0.6.4/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "doc_cfg" + ] + } + }, + "playground": { + "all-features": true + } + }, + "publish": null, + "authors": [ + "The Rand Project Developers", + "The Rust Project Developers" + ], + "categories": [ + "algorithms", + "no-std" + ], + "keywords": [ + "random", + "rng" + ], + "readme": null, + "repository": "https://github.com/rust-random/rand", + "homepage": "https://rust-random.github.io/book", + "documentation": "https://docs.rs/rand_core", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "regex", + "version": "1.12.3", + "id": "registry+https://github.com/rust-lang/crates.io-index#regex@1.12.3", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-1.12.3/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs_regex" + ] + } + } + }, + "publish": null, + "authors": [ + "The Rust Project Developers", + "Andrew Gallant " + ], + "categories": [ + "text-processing" + ], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/regex", + "homepage": "https://github.com/rust-lang/regex", + "documentation": "https://docs.rs/regex", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.65" + }, + { + "name": "regex-automata", + "version": "0.4.14", + "id": "registry+https://github.com/rust-lang/crates.io-index#regex-automata@0.4.14", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-automata-0.4.14/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs_regex" + ] + } + } + }, + "publish": null, + "authors": [ + "The Rust Project Developers", + "Andrew Gallant " + ], + "categories": [ + "text-processing" + ], + "keywords": [ + "regex", + "dfa", + "automata", + "automaton", + "nfa" + ], + "readme": null, + "repository": "https://github.com/rust-lang/regex", + "homepage": "https://github.com/rust-lang/regex/tree/master/regex-automata", + "documentation": "https://docs.rs/regex-automata", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.65" + }, + { + "name": "regex-syntax", + "version": "0.8.10", + "id": "registry+https://github.com/rust-lang/crates.io-index#regex-syntax@0.8.10", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-syntax-0.8.10/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs_regex" + ] + } + } + }, + "publish": null, + "authors": [ + "The Rust Project Developers", + "Andrew Gallant " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/regex", + "homepage": "https://github.com/rust-lang/regex/tree/master/regex-syntax", + "documentation": "https://docs.rs/regex-syntax", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.65" + }, + { + "name": "ring", + "version": "0.17.14", + "id": "registry+https://github.com/rust-lang/crates.io-index#ring@0.17.14", + "license": "Apache-2.0 AND ISC", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ring-0.17.14/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true + } + } + }, + "publish": null, + "authors": [], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "crypto", + "cryptography", + "rand", + "ECC", + "RSA" + ], + "readme": null, + "repository": "https://github.com/briansmith/ring", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": "ring_core_0_17_14_", + "default_run": null, + "rust_version": "1.66.0" + }, + { + "name": "rustc-demangle", + "version": "0.1.27", + "id": "registry+https://github.com/rust-lang/crates.io-index#rustc-demangle@0.1.27", + "license": "MIT/Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustc-demangle-0.1.27/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "std" + ], + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "Alex Crichton " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/rust-lang/rustc-demangle", + "homepage": "https://github.com/rust-lang/rustc-demangle", + "documentation": "https://docs.rs/rustc-demangle", + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "rustls", + "version": "0.23.45", + "id": "registry+https://github.com/rust-lang/crates.io-index#rustls@0.23.45", + "license": "Apache-2.0 OR ISC OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.45/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "read_buf", + "ring" + ], + "rustdoc-args": [ + "--cfg", + "rustls_docsrs" + ] + } + }, + "cargo_check_external_types": { + "allowed_external_types": [ + "rustls_pki_types", + "rustls_pki_types::*" + ] + }, + "cargo-semver-checks": { + "lints": { + "enum_no_repr_variant_discriminant_changed": "warn" + } + } + }, + "publish": null, + "authors": [], + "categories": [ + "network-programming", + "cryptography" + ], + "keywords": [], + "readme": null, + "repository": "https://github.com/rustls/rustls", + "homepage": "https://github.com/rustls/rustls", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "rustls-pki-types", + "version": "1.14.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#rustls-pki-types@1.14.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-pki-types-1.14.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "rustls_pki_types_docsrs" + ] + } + }, + "cargo_check_external_types": { + "allowed_external_types": [ + "zeroize::Zeroize" + ] + } + }, + "publish": null, + "authors": [], + "categories": [ + "network-programming", + "data-structures", + "cryptography" + ], + "keywords": [], + "readme": null, + "repository": "https://github.com/rustls/pki-types", + "homepage": "https://github.com/rustls/pki-types", + "documentation": "https://docs.rs/rustls-pki-types", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.60" + }, + { + "name": "rustls-webpki", + "version": "0.103.15", + "id": "registry+https://github.com/rust-lang/crates.io-index#rustls-webpki@0.103.15", + "license": "ISC", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-webpki-0.103.15/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "aws-lc-rs", + "ring" + ], + "rustdoc-args": [ + "--cfg", + "webpki_docsrs" + ] + } + }, + "cargo_check_external_types": { + "allowed_external_types": [ + "rustls_pki_types::*", + "rustls_pki_types" + ] + }, + "cargo-semver-checks": { + "lints": { + "enum_variant_marked_deprecated": "warn" + } + } + }, + "publish": null, + "authors": [], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [], + "readme": null, + "repository": "https://github.com/rustls/webpki", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "rx509", + "version": "0.2.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#rx509@0.2.1", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rx509-0.2.1/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Step Function I/O " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": null, + "homepage": "https://github.com/stepfunc/rasn/", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "salsa20", + "version": "0.10.2", + "id": "registry+https://github.com/rust-lang/crates.io-index#salsa20@0.10.2", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/salsa20-0.10.2/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "crypto", + "stream-cipher", + "trait", + "xsalsa20" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/stream-ciphers", + "homepage": null, + "documentation": "https://docs.rs/salsa20", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.56" + }, + { + "name": "scopeguard", + "version": "1.2.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#scopeguard@1.2.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scopeguard-1.2.0/Cargo.toml", + "metadata": { + "release": { + "no-dev-version": true + } + }, + "publish": null, + "authors": [ + "bluss" + ], + "categories": [ + "rust-patterns", + "no-std" + ], + "keywords": [ + "scope-guard", + "defer", + "panic", + "unwind" + ], + "readme": null, + "repository": "https://github.com/bluss/scopeguard", + "homepage": null, + "documentation": "https://docs.rs/scopeguard/", + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "scrypt", + "version": "0.11.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#scrypt@0.11.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scrypt-0.11.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "authentication", + "cryptography", + "no-std" + ], + "keywords": [ + "crypto", + "hashing", + "password", + "phf" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/password-hashes/tree/master/scrypt", + "homepage": null, + "documentation": "https://docs.rs/scrypt", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.60" + }, + { + "name": "scursor", + "version": "0.2.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#scursor@0.2.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scursor-0.2.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/stepfunc/scursor", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "semver", + "version": "1.0.28", + "id": "registry+https://github.com/rust-lang/crates.io-index#semver@1.0.28", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/semver-1.0.28/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "serde" + ], + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org" + ] + } + }, + "playground": { + "features": [ + "serde" + ] + } + }, + "publish": null, + "authors": [ + "David Tolnay " + ], + "categories": [ + "data-structures", + "no-std" + ], + "keywords": [ + "cargo" + ], + "readme": null, + "repository": "https://github.com/dtolnay/semver", + "homepage": null, + "documentation": "https://docs.rs/semver", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.68" + }, + { + "name": "serde", + "version": "1.0.228", + "id": "registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/Cargo.toml", + "metadata": { + "playground": { + "features": [ + "derive", + "rc" + ] + }, + "docs": { + "rs": { + "features": [ + "derive", + "rc", + "unstable" + ], + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org" + ] + } + } + }, + "publish": null, + "authors": [ + "Erick Tryzelaar ", + "David Tolnay " + ], + "categories": [ + "encoding", + "no-std", + "no-std::no-alloc" + ], + "keywords": [ + "serde", + "serialization", + "no_std" + ], + "readme": null, + "repository": "https://github.com/serde-rs/serde", + "homepage": "https://serde.rs", + "documentation": "https://docs.rs/serde", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.56" + }, + { + "name": "serde_core", + "version": "1.0.228", + "id": "registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/Cargo.toml", + "metadata": { + "playground": { + "features": [ + "rc", + "result" + ] + }, + "docs": { + "rs": { + "features": [ + "rc", + "result", + "unstable" + ], + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org" + ] + } + } + }, + "publish": null, + "authors": [ + "Erick Tryzelaar ", + "David Tolnay " + ], + "categories": [ + "encoding", + "no-std", + "no-std::no-alloc" + ], + "keywords": [ + "serde", + "serialization", + "no_std" + ], + "readme": null, + "repository": "https://github.com/serde-rs/serde", + "homepage": "https://serde.rs", + "documentation": "https://docs.rs/serde_core", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.56" + }, + { + "name": "serde_derive", + "version": "1.0.228", + "id": "registry+https://github.com/rust-lang/crates.io-index#serde_derive@1.0.228", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_derive-1.0.228/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org" + ] + } + } + }, + "publish": null, + "authors": [ + "Erick Tryzelaar ", + "David Tolnay " + ], + "categories": [ + "no-std", + "no-std::no-alloc" + ], + "keywords": [ + "serde", + "serialization", + "no_std", + "derive" + ], + "readme": null, + "repository": "https://github.com/serde-rs/serde", + "homepage": "https://serde.rs", + "documentation": "https://serde.rs/derive.html", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.61" + }, + { + "name": "serde_json", + "version": "1.0.149", + "id": "registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "preserve_order", + "raw_value", + "unbounded_depth" + ], + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org" + ] + } + }, + "playground": { + "features": [ + "float_roundtrip", + "raw_value", + "unbounded_depth" + ] + } + }, + "publish": null, + "authors": [ + "Erick Tryzelaar ", + "David Tolnay " + ], + "categories": [ + "encoding", + "parser-implementations", + "no-std" + ], + "keywords": [ + "json", + "serde", + "serialization" + ], + "readme": null, + "repository": "https://github.com/serde-rs/json", + "homepage": null, + "documentation": "https://docs.rs/serde_json", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.68" + }, + { + "name": "serialport", + "version": "4.9.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#serialport@4.9.0", + "license": "MPL-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serialport-4.9.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Bryant Mairs ", + "Jesse Braham " + ], + "categories": [ + "hardware-support" + ], + "keywords": [ + "serial", + "hardware", + "system", + "RS232" + ], + "readme": null, + "repository": "https://github.com/serialport/serialport-rs", + "homepage": null, + "documentation": "https://docs.rs/serialport", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.59.0" + }, + { + "name": "sfio-promise", + "version": "0.2.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#sfio-promise@0.2.0", + "license": null, + "license_file": "LICENSE", + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-promise-0.2.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/stepfunc/promise", + "homepage": "https://github.com/stepfunc/promise", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "sfio-rustls-config", + "version": "0.4.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#sfio-rustls-config@0.4.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-rustls-config-0.4.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Step Function I/O LLC " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/stepfunc/rustls-config", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.74" + }, + { + "name": "sfio-tokio-ffi", + "version": "0.9.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#sfio-tokio-ffi@0.9.0", + "license": null, + "license_file": "LICENSE", + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-tokio-ffi-0.9.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/stepfunc/tokio-ffi", + "homepage": "https://github.com/stepfunc/tokio-ffi", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "sfio-tracing-ffi", + "version": "0.9.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#sfio-tracing-ffi@0.9.0", + "license": null, + "license_file": "LICENSE", + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-tracing-ffi-0.9.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/stepfunc/tracing-ffi", + "homepage": "https://github.com/stepfunc/tracing-ffi", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "sha2", + "version": "0.10.9", + "id": "registry+https://github.com/rust-lang/crates.io-index#sha2@0.10.9", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sha2-0.10.9/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "crypto", + "sha2", + "hash", + "digest" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/hashes", + "homepage": null, + "documentation": "https://docs.rs/sha2", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "sharded-slab", + "version": "0.1.7", + "id": "registry+https://github.com/rust-lang/crates.io-index#sharded-slab@0.1.7", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sharded-slab-0.1.7/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "Eliza Weisman " + ], + "categories": [ + "memory-management", + "data-structures", + "concurrency" + ], + "keywords": [ + "slab", + "allocator", + "lock-free", + "atomic" + ], + "readme": null, + "repository": "https://github.com/hawkw/sharded-slab", + "homepage": "https://github.com/hawkw/sharded-slab", + "documentation": "https://docs.rs/sharded-slab/", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.42.0" + }, + { + "name": "shlex", + "version": "1.3.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#shlex@1.3.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/shlex-1.3.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "comex ", + "Fenhl ", + "Adrian Taylor ", + "Alex Touchet ", + "Daniel Parks ", + "Garrett Berg " + ], + "categories": [ + "command-line-interface", + "parser-implementations" + ], + "keywords": [], + "readme": null, + "repository": "https://github.com/comex/rust-shlex", + "homepage": null, + "documentation": null, + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": "1.46.0" + }, + { + "name": "slab", + "version": "0.4.12", + "id": "registry+https://github.com/rust-lang/crates.io-index#slab@0.4.12", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/slab-0.4.12/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Carl Lerche " + ], + "categories": [ + "memory-management", + "data-structures", + "no-std" + ], + "keywords": [ + "slab", + "allocator", + "no_std" + ], + "readme": null, + "repository": "https://github.com/tokio-rs/slab", + "homepage": null, + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.51" + }, + { + "name": "smallvec", + "version": "1.15.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#smallvec@1.15.1", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/smallvec-1.15.1/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs", + "--generate-link-to-definition" + ] + } + } + }, + "publish": null, + "authors": [ + "The Servo Project Developers" + ], + "categories": [ + "data-structures" + ], + "keywords": [ + "small", + "vec", + "vector", + "stack", + "no_std" + ], + "readme": null, + "repository": "https://github.com/servo/rust-smallvec", + "homepage": null, + "documentation": "https://docs.rs/smallvec/", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "socket2", + "version": "0.6.3", + "id": "registry+https://github.com/rust-lang/crates.io-index#socket2@0.6.3", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/socket2-0.6.3/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "default-target": "x86_64-unknown-linux-gnu", + "targets": [ + "aarch64-apple-ios", + "aarch64-linux-android", + "armv7-linux-androideabi", + "i686-linux-android", + "x86_64-apple-darwin", + "x86_64-pc-solaris", + "x86_64-pc-windows-msvc", + "x86_64-unknown-freebsd", + "x86_64-unknown-fuchsia", + "x86_64-unknown-illumos", + "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-musl", + "x86_64-unknown-netbsd", + "x86_64-unknown-redox" + ] + } + }, + "playground": { + "features": [ + "all" + ] + }, + "cargo_check_external_types": { + "allowed_external_types": [ + "libc::socklen_t", + "libc::*::socklen_t", + "libc::sa_family_t", + "libc::*::sa_family_t", + "windows_sys::Win32::Networking::WinSock::socklen_t", + "windows_sys::Win32::Networking::WinSock::ADDRESS_FAMILY" + ] + } + }, + "publish": null, + "authors": [ + "Alex Crichton ", + "Thomas de Zeeuw " + ], + "categories": [ + "api-bindings", + "network-programming" + ], + "keywords": [ + "io", + "socket", + "network" + ], + "readme": null, + "repository": "https://github.com/rust-lang/socket2", + "homepage": "https://github.com/rust-lang/socket2", + "documentation": "https://docs.rs/socket2", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.70" + }, + { + "name": "spki", + "version": "0.7.3", + "id": "registry+https://github.com/rust-lang/crates.io-index#spki@0.7.3", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spki-0.7.3/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "RustCrypto Developers" + ], + "categories": [ + "cryptography", + "data-structures", + "encoding", + "no-std" + ], + "keywords": [ + "crypto", + "x509" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/formats/tree/master/spki", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.65" + }, + { + "name": "strsim", + "version": "0.11.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#strsim@0.11.1", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/strsim-0.11.1/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Danny Guo ", + "maxbachmann " + ], + "categories": [ + "text-processing" + ], + "keywords": [ + "string", + "similarity", + "Hamming", + "Levenshtein", + "Jaro" + ], + "readme": null, + "repository": "https://github.com/rapidfuzz/strsim-rs", + "homepage": "https://github.com/rapidfuzz/strsim-rs", + "documentation": "https://docs.rs/strsim/", + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": "1.56" + }, + { + "name": "subtle", + "version": "2.6.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#subtle@2.6.1", + "license": "BSD-3-Clause", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Isis Lovecruft ", + "Henry de Valence " + ], + "categories": [ + "cryptography", + "no-std" + ], + "keywords": [ + "cryptography", + "crypto", + "constant-time", + "utilities" + ], + "readme": null, + "repository": "https://github.com/dalek-cryptography/subtle", + "homepage": "https://dalek.rs/", + "documentation": "https://docs.rs/subtle", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "syn", + "version": "2.0.117", + "id": "registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/syn-2.0.117/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extend-css=src/gen/token.css", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org" + ] + } + }, + "playground": { + "features": [ + "full", + "visit", + "visit-mut", + "fold", + "extra-traits" + ] + } + }, + "publish": null, + "authors": [ + "David Tolnay " + ], + "categories": [ + "development-tools::procedural-macro-helpers", + "parser-implementations" + ], + "keywords": [ + "macros", + "syn" + ], + "readme": null, + "repository": "https://github.com/dtolnay/syn", + "homepage": null, + "documentation": "https://docs.rs/syn", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "thiserror", + "version": "2.0.18", + "id": "registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org" + ] + } + } + }, + "publish": null, + "authors": [ + "David Tolnay " + ], + "categories": [ + "rust-patterns", + "no-std" + ], + "keywords": [ + "error", + "error-handling", + "derive" + ], + "readme": null, + "repository": "https://github.com/dtolnay/thiserror", + "homepage": null, + "documentation": "https://docs.rs/thiserror", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.68" + }, + { + "name": "thiserror-impl", + "version": "2.0.18", + "id": "registry+https://github.com/rust-lang/crates.io-index#thiserror-impl@2.0.18", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-impl-2.0.18/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org", + "--extern-html-root-url=proc_macro=https://doc.rust-lang.org" + ] + } + } + }, + "publish": null, + "authors": [ + "David Tolnay " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/dtolnay/thiserror", + "homepage": null, + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.68" + }, + { + "name": "thread_local", + "version": "1.1.9", + "id": "registry+https://github.com/rust-lang/crates.io-index#thread_local@1.1.9", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thread_local-1.1.9/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Amanieu d'Antras " + ], + "categories": [], + "keywords": [ + "thread_local", + "concurrent", + "thread" + ], + "readme": null, + "repository": "https://github.com/Amanieu/thread_local-rs", + "homepage": null, + "documentation": "https://docs.rs/thread_local/", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.63" + }, + { + "name": "tokio", + "version": "1.52.1", + "id": "registry+https://github.com/rust-lang/crates.io-index#tokio@1.52.1", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.52.1/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs", + "--cfg", + "tokio_unstable" + ], + "rustc-args": [ + "--cfg", + "tokio_unstable" + ] + } + }, + "playground": { + "features": [ + "full", + "test-util" + ] + }, + "cargo_check_external_types": { + "allowed_external_types": [ + "bytes::buf::buf_impl::Buf", + "bytes::buf::buf_mut::BufMut", + "tokio_macros::*" + ] + } + }, + "publish": null, + "authors": [ + "Tokio Contributors " + ], + "categories": [ + "asynchronous", + "network-programming" + ], + "keywords": [ + "io", + "async", + "non-blocking", + "futures" + ], + "readme": null, + "repository": "https://github.com/tokio-rs/tokio", + "homepage": "https://tokio.rs", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "tokio-macros", + "version": "2.7.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#tokio-macros@2.7.0", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-macros-2.7.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true + } + } + }, + "publish": null, + "authors": [ + "Tokio Contributors " + ], + "categories": [ + "asynchronous" + ], + "keywords": [], + "readme": null, + "repository": "https://github.com/tokio-rs/tokio", + "homepage": "https://tokio.rs", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "tokio-rustls", + "version": "0.26.4", + "id": "registry+https://github.com/rust-lang/crates.io-index#tokio-rustls@0.26.4", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-rustls-0.26.4/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [], + "categories": [ + "asynchronous", + "cryptography", + "network-programming" + ], + "keywords": [], + "readme": null, + "repository": "https://github.com/rustls/tokio-rustls", + "homepage": "https://github.com/rustls/tokio-rustls", + "documentation": "https://docs.rs/tokio-rustls", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "tokio-serial", + "version": "5.4.5", + "id": "registry+https://github.com/rust-lang/crates.io-index#tokio-serial@5.4.5", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-serial-5.4.5/Cargo.toml", + "metadata": { + "msrv": "1.46.0", + "docs": { + "rs": { + "features": [ + "codec" + ] + } + } + }, + "publish": null, + "authors": [ + "Zac Berkowitz " + ], + "categories": [ + "asynchronous", + "hardware-support" + ], + "keywords": [ + "rs232", + "serial", + "tokio" + ], + "readme": null, + "repository": "https://github.com/berkowski/tokio-serial", + "homepage": "https://github.com/berkowski/tokio-serial", + "documentation": "http://docs.rs/tokio-serial", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "tracing", + "version": "0.1.44", + "id": "registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-0.1.44/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs", + "--cfg", + "tracing_unstable" + ], + "rustc-args": [ + "--cfg", + "tracing_unstable" + ] + } + } + }, + "publish": null, + "authors": [ + "Eliza Weisman ", + "Tokio Contributors " + ], + "categories": [ + "development-tools::debugging", + "development-tools::profiling", + "asynchronous", + "no-std" + ], + "keywords": [ + "logging", + "tracing", + "metrics", + "async" + ], + "readme": null, + "repository": "https://github.com/tokio-rs/tracing", + "homepage": "https://tokio.rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.65.0" + }, + { + "name": "tracing-attributes", + "version": "0.1.31", + "id": "registry+https://github.com/rust-lang/crates.io-index#tracing-attributes@0.1.31", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-attributes-0.1.31/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Tokio Contributors ", + "Eliza Weisman ", + "David Barsky " + ], + "categories": [ + "development-tools::debugging", + "development-tools::profiling", + "asynchronous" + ], + "keywords": [ + "logging", + "tracing", + "macro", + "instrument", + "log" + ], + "readme": null, + "repository": "https://github.com/tokio-rs/tracing", + "homepage": "https://tokio.rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.65.0" + }, + { + "name": "tracing-core", + "version": "0.1.36", + "id": "registry+https://github.com/rust-lang/crates.io-index#tracing-core@0.1.36", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-core-0.1.36/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs", + "--cfg", + "tracing_unstable" + ], + "rustc-args": [ + "--cfg", + "tracing_unstable" + ] + } + } + }, + "publish": null, + "authors": [ + "Tokio Contributors " + ], + "categories": [ + "development-tools::debugging", + "development-tools::profiling", + "asynchronous" + ], + "keywords": [ + "logging", + "tracing", + "profiling" + ], + "readme": null, + "repository": "https://github.com/tokio-rs/tracing", + "homepage": "https://tokio.rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.65.0" + }, + { + "name": "tracing-log", + "version": "0.2.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#tracing-log@0.2.0", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-log-0.2.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "Tokio Contributors " + ], + "categories": [ + "development-tools::debugging", + "asynchronous" + ], + "keywords": [ + "logging", + "tracing", + "log" + ], + "readme": null, + "repository": "https://github.com/tokio-rs/tracing", + "homepage": "https://tokio.rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.56.0" + }, + { + "name": "tracing-serde", + "version": "0.2.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#tracing-serde@0.2.0", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-serde-0.2.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Tokio Contributors " + ], + "categories": [ + "development-tools::debugging", + "development-tools::profiling", + "asynchronous", + "encoding" + ], + "keywords": [ + "logging", + "tracing", + "serialization" + ], + "readme": null, + "repository": "https://github.com/tokio-rs/tracing", + "homepage": "https://tokio.rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.63.0" + }, + { + "name": "tracing-subscriber", + "version": "0.3.23", + "id": "registry+https://github.com/rust-lang/crates.io-index#tracing-subscriber@0.3.23", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-subscriber-0.3.23/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "Eliza Weisman ", + "David Barsky ", + "Tokio Contributors " + ], + "categories": [ + "development-tools::debugging", + "development-tools::profiling", + "asynchronous" + ], + "keywords": [ + "logging", + "tracing", + "metrics", + "subscriber" + ], + "readme": null, + "repository": "https://github.com/tokio-rs/tracing", + "homepage": "https://tokio.rs", + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.65.0" + }, + { + "name": "typenum", + "version": "1.19.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#typenum@1.19.0", + "license": "MIT OR Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/typenum-1.19.0/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "i128", + "const-generics" + ], + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + }, + "playground": { + "features": [ + "i128", + "const-generics" + ] + } + }, + "publish": null, + "authors": [ + "Paho Lurie-Gregg ", + "Andre Bogus " + ], + "categories": [ + "no-std" + ], + "keywords": [], + "readme": null, + "repository": "https://github.com/paholg/typenum", + "homepage": null, + "documentation": "https://docs.rs/typenum", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": "1.37.0" + }, + { + "name": "unescaper", + "version": "0.1.8", + "id": "registry+https://github.com/rust-lang/crates.io-index#unescaper@0.1.8", + "license": "GPL-3.0/MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/unescaper-0.1.8/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true + } + } + }, + "publish": null, + "authors": [ + "Hack Ink ", + "Xavier Lau " + ], + "categories": [], + "keywords": [ + "escape", + "string", + "unescape" + ], + "readme": null, + "repository": "https://github.com/hack-ink/unescaper", + "homepage": "https://hack.ink/unescaper", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "unicode-ident", + "version": "1.0.24", + "id": "registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24", + "license": "(MIT OR Apache-2.0) AND Unicode-3.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/unicode-ident-1.0.24/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org", + "--extern-html-root-url=alloc=https://doc.rust-lang.org", + "--extern-html-root-url=std=https://doc.rust-lang.org" + ] + } + } + }, + "publish": null, + "authors": [ + "David Tolnay " + ], + "categories": [ + "development-tools::procedural-macro-helpers", + "no-std", + "no-std::no-alloc" + ], + "keywords": [ + "unicode", + "xid" + ], + "readme": null, + "repository": "https://github.com/dtolnay/unicode-ident", + "homepage": null, + "documentation": "https://docs.rs/unicode-ident", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.71" + }, + { + "name": "untrusted", + "version": "0.9.0", + "id": "registry+https://github.com/rust-lang/crates.io-index#untrusted@0.9.0", + "license": "ISC", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/untrusted-0.9.0/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Brian Smith " + ], + "categories": [], + "keywords": [], + "readme": null, + "repository": "https://github.com/briansmith/untrusted", + "homepage": null, + "documentation": "https://briansmith.org/rustdoc/untrusted/", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "utf8parse", + "version": "0.2.2", + "id": "registry+https://github.com/rust-lang/crates.io-index#utf8parse@0.2.2", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/utf8parse-0.2.2/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Joe Wilm ", + "Christian Duerr " + ], + "categories": [ + "parsing", + "no-std" + ], + "keywords": [ + "utf8", + "parse", + "table" + ], + "readme": null, + "repository": "https://github.com/alacritty/vte", + "homepage": null, + "documentation": "https://docs.rs/utf8parse/", + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "version_check", + "version": "0.9.5", + "id": "registry+https://github.com/rust-lang/crates.io-index#version_check@0.9.5", + "license": "MIT/Apache-2.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/version_check-0.9.5/Cargo.toml", + "metadata": null, + "publish": null, + "authors": [ + "Sergio Benitez " + ], + "categories": [], + "keywords": [ + "version", + "rustc", + "minimum", + "check" + ], + "readme": null, + "repository": "https://github.com/SergioBenitez/version_check", + "homepage": null, + "documentation": "https://docs.rs/version_check/", + "edition": "2015", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "xxhash-rust", + "version": "0.8.15", + "id": "registry+https://github.com/rust-lang/crates.io-index#xxhash-rust@0.8.15", + "license": "BSL-1.0", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/xxhash-rust-0.8.15/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "features": [ + "xxh32", + "const_xxh32", + "xxh64", + "const_xxh64", + "xxh3", + "const_xxh3" + ] + } + } + }, + "publish": null, + "authors": [ + "Douman " + ], + "categories": [ + "algorithms", + "no-std::no-alloc" + ], + "keywords": [ + "hash", + "xxhash", + "xxh3", + "hasher", + "no-std" + ], + "readme": null, + "repository": "https://github.com/DoumanAsh/xxhash-rust", + "homepage": null, + "documentation": null, + "edition": "2018", + "links": null, + "default_run": null, + "rust_version": null + }, + { + "name": "zeroize", + "version": "1.8.2", + "id": "registry+https://github.com/rust-lang/crates.io-index#zeroize@1.8.2", + "license": "Apache-2.0 OR MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zeroize-1.8.2/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "all-features": true, + "rustdoc-args": [ + "--cfg", + "docsrs" + ] + } + } + }, + "publish": null, + "authors": [ + "The RustCrypto Project Developers" + ], + "categories": [ + "cryptography", + "memory-management", + "no-std", + "os" + ], + "keywords": [ + "memory", + "memset", + "secure", + "volatile", + "zero" + ], + "readme": null, + "repository": "https://github.com/RustCrypto/utils", + "homepage": "https://github.com/RustCrypto/utils/tree/master/zeroize", + "documentation": null, + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.60" + }, + { + "name": "zmij", + "version": "1.0.21", + "id": "registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21", + "license": "MIT", + "license_file": null, + "description": null, + "source": "registry+https://github.com/rust-lang/crates.io-index", + "dependencies": [], + "targets": [], + "features": {}, + "manifest_path": "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/Cargo.toml", + "metadata": { + "docs": { + "rs": { + "targets": [ + "x86_64-unknown-linux-gnu" + ], + "rustdoc-args": [ + "--generate-link-to-definition", + "--generate-macro-expansion", + "--extern-html-root-url=core=https://doc.rust-lang.org" + ] + } + } + }, + "publish": null, + "authors": [ + "David Tolnay " + ], + "categories": [ + "value-formatting", + "no-std", + "no-std::no-alloc" + ], + "keywords": [ + "float" + ], + "readme": null, + "repository": "https://github.com/dtolnay/zmij", + "homepage": null, + "documentation": "https://docs.rs/zmij", + "edition": "2021", + "links": null, + "default_run": null, + "rust_version": "1.71" + } + ], + "workspace_members": [ + "path+file:///build/dnp3/dnp3#1.7.0", + "path+file:///build/dnp3/examples/master#example-master@0.1.0", + "path+file:///build/dnp3/examples/cli-utils#dnp3-cli-utils@0.1.0", + "path+file:///build/dnp3/examples/outstation#example-outstation@0.1.0", + "path+file:///build/dnp3/examples/master_tcp_server#example-master-tcp-server@0.1.0", + "path+file:///build/dnp3/examples/perf#perf-tests@0.1.0", + "path+file:///build/dnp3/ffi/dnp3-schema#1.7.0", + "path+file:///build/dnp3/ffi/dnp3-ffi#1.7.0", + "path+file:///build/dnp3/ffi/dnp3-bindings#1.7.0", + "path+file:///build/dnp3/ffi/dnp3-ffi-java#1.7.0" + ], + "workspace_default_members": [ + "path+file:///build/dnp3/dnp3#1.7.0", + "path+file:///build/dnp3/examples/master#example-master@0.1.0", + "path+file:///build/dnp3/examples/cli-utils#dnp3-cli-utils@0.1.0", + "path+file:///build/dnp3/examples/outstation#example-outstation@0.1.0", + "path+file:///build/dnp3/examples/master_tcp_server#example-master-tcp-server@0.1.0", + "path+file:///build/dnp3/examples/perf#perf-tests@0.1.0", + "path+file:///build/dnp3/ffi/dnp3-schema#1.7.0", + "path+file:///build/dnp3/ffi/dnp3-ffi#1.7.0", + "path+file:///build/dnp3/ffi/dnp3-bindings#1.7.0", + "path+file:///build/dnp3/ffi/dnp3-ffi-java#1.7.0" + ], + "resolve": null, + "target_directory": "/build/dnp3/target", + "build_directory": "/build/dnp3/target", + "version": 1, + "workspace_root": "/build/dnp3", + "metadata": null +} \ No newline at end of file diff --git a/allow-list/tests/fixtures/dnp3/targets/aws/build.json b/allow-list/tests/fixtures/dnp3/targets/aws/build.json new file mode 100644 index 0000000..7b0f597 --- /dev/null +++ b/allow-list/tests/fixtures/dnp3/targets/aws/build.json @@ -0,0 +1,175 @@ +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/proc-macro2-1.0.106/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/proc-macro2-1.0.106/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","proc-macro"],"filenames":["/build/dnp3/target/release/build/proc-macro2-986587f949cb3616/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.45/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.45/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","proc-macro"],"filenames":["/build/dnp3/target/release/build/quote-c93d442eb9933478/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/unicode-ident-1.0.24/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"unicode_ident","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/unicode-ident-1.0.24/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libunicode_ident-eb594fc5b763ee92.rlib","/build/dnp3/target/release/deps/libunicode_ident-eb594fc5b763ee92.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#libc@0.2.185","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/build/libc-e52c3cf8c9087f8a/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#version_check@0.9.5","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/version_check-0.9.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"version_check","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/version_check-0.9.5/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libversion_check-23278575be3c0f59.rlib","/build/dnp3/target/release/deps/libversion_check-23278575be3c0f59.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#typenum@1.19.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/typenum-1.19.0/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/typenum-1.19.0/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/build/typenum-b8d3f63d8a932f1e/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#dunce@1.0.5","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/dunce-1.0.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"dunce","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/dunce-1.0.5/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libdunce-47dea079ba20012f.rlib","/build/dnp3/target/release/deps/libdunce-47dea079ba20012f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["result","std"],"filenames":["/build/dnp3/target/release/build/serde_core-e52075bc2b27c91d/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/build/thiserror-c2e697b5955ec78e/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg-if-1.0.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cfg_if","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg-if-1.0.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcfg_if-3a5641228175f401.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcfg_if-3a5641228175f401.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#libc@0.2.185","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","extra_traits","std"],"filenames":["/build/dnp3/target/release/build/libc-d94ce3dda6b693b5/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/proc-macro2-1.0.106/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"proc_macro2","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/proc-macro2-1.0.106/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","proc-macro"],"filenames":["/build/dnp3/target/release/deps/libproc_macro2-09a9c2d5277a398f.rlib","/build/dnp3/target/release/deps/libproc_macro2-09a9c2d5277a398f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#generic-array@0.14.7","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/build.rs","edition":"2015","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["more_lengths"],"filenames":["/build/dnp3/target/release/build/generic-array-64cb29654dbed717/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#shlex@1.3.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/shlex-1.3.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"shlex","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/shlex-1.3.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libshlex-b179ddb968436a02.rlib","/build/dnp3/target/release/deps/libshlex-b179ddb968436a02.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#find-msvc-tools@0.1.9","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/find-msvc-tools-0.1.9/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"find_msvc_tools","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/find-msvc-tools-0.1.9/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libfind_msvc_tools-c2e0b1f19d8c6254.rlib","/build/dnp3/target/release/deps/libfind_msvc_tools-c2e0b1f19d8c6254.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/build/zmij-6b72ac5b6722cab2/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/memchr-2.8.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"memchr","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/memchr-2.8.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","std"],"filenames":["/build/dnp3/target/release/deps/libmemchr-0b36fee4e09e12a3.rlib","/build/dnp3/target/release/deps/libmemchr-0b36fee4e09e12a3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#fs_extra@1.3.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/fs_extra-1.3.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"fs_extra","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/fs_extra-1.3.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libfs_extra-e74f69431bcbd4a3.rlib","/build/dnp3/target/release/deps/libfs_extra-e74f69431bcbd4a3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/build/serde_json-c1f9c3dcffe62a42/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#zeroize@1.8.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zeroize-1.8.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"zeroize","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zeroize-1.8.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libzeroize-aa9c3200ffc9bb97.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libzeroize-aa9c3200ffc9bb97.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pkg-config@0.3.34","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkg-config-0.3.34/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pkg_config","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkg-config-0.3.34/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libpkg_config-5a55ca97e2d33449.rlib","/build/dnp3/target/release/deps/libpkg_config-5a55ca97e2d33449.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#subtle@2.6.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"subtle","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsubtle-2c5af15982bd0d6a.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsubtle-2c5af15982bd0d6a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#log@0.4.29","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/log-0.4.29/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"log","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/log-0.4.29/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblog-fb385694826f2088.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblog-fb385694826f2088.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#utf8parse@0.2.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/utf8parse-0.2.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"utf8parse","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/utf8parse-0.2.2/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default"],"filenames":["/build/dnp3/target/release/deps/libutf8parse-73a0c37e0c4b036d.rlib","/build/dnp3/target/release/deps/libutf8parse-73a0c37e0c4b036d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/once_cell-1.21.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"once_cell","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/once_cell-1.21.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default","race","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libonce_cell-6e50d1ba9ef3d8ad.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libonce_cell-6e50d1ba9ef3d8ad.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#colorchoice@1.0.5","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/colorchoice-1.0.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"colorchoice","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/colorchoice-1.0.5/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libcolorchoice-c697909ffec6e90b.rlib","/build/dnp3/target/release/deps/libcolorchoice-c697909ffec6e90b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#anstyle-query@1.1.5","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-query-1.1.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"anstyle_query","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-query-1.1.5/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libanstyle_query-9b42a193c1050938.rlib","/build/dnp3/target/release/deps/libanstyle_query-9b42a193c1050938.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#object@0.37.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/object-0.37.3/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/object-0.37.3/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["archive","coff","elf","macho","pe","read_core","unaligned","xcoff"],"filenames":["/build/dnp3/target/release/build/object-f29e28d21cf1c13a/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#is_terminal_polyfill@1.70.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/is_terminal_polyfill-1.70.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"is_terminal_polyfill","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/is_terminal_polyfill-1.70.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default"],"filenames":["/build/dnp3/target/release/deps/libis_terminal_polyfill-ea6316c19614d7f3.rlib","/build/dnp3/target/release/deps/libis_terminal_polyfill-ea6316c19614d7f3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#anstyle@1.0.14","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-1.0.14/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"anstyle","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-1.0.14/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libanstyle-ecb2a8503060039e.rlib","/build/dnp3/target/release/deps/libanstyle-ecb2a8503060039e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#aws-lc-rs@1.18.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-rs-1.18.1/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-rs-1.18.1/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["aws-lc-sys","prebuilt-nasm"],"filenames":["/build/dnp3/target/release/build/aws-lc-rs-215d2300dd9b796d/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#regex-syntax@0.8.10","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-syntax-0.8.10/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"regex_syntax","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-syntax-0.8.10/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std","unicode","unicode-age","unicode-bool","unicode-case","unicode-gencat","unicode-perl","unicode-script","unicode-segment"],"filenames":["/build/dnp3/target/release/deps/libregex_syntax-792826352cca3ffb.rlib","/build/dnp3/target/release/deps/libregex_syntax-792826352cca3ffb.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#adler2@2.0.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/adler2-2.0.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"adler2","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/adler2-2.0.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libadler2-0a85de5109f6fe71.rlib","/build/dnp3/target/release/deps/libadler2-0a85de5109f6fe71.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/once_cell-1.21.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"once_cell","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/once_cell-1.21.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default","race","std"],"filenames":["/build/dnp3/target/release/deps/libonce_cell-020eb50cb4eb8f6c.rlib","/build/dnp3/target/release/deps/libonce_cell-020eb50cb4eb8f6c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#heck@0.5.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/heck-0.5.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"heck","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/heck-0.5.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libheck-93c7fa174c74aabf.rlib","/build/dnp3/target/release/deps/libheck-93c7fa174c74aabf.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#strsim@0.11.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/strsim-0.11.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"strsim","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/strsim-0.11.1/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libstrsim-8f54055135456a8d.rlib","/build/dnp3/target/release/deps/libstrsim-8f54055135456a8d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","derive","serde_derive","std"],"filenames":["/build/dnp3/target/release/build/serde-214c13a0b92d23df/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#gimli@0.32.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/gimli-0.32.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"gimli","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/gimli-0.32.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["read","read-core"],"filenames":["/build/dnp3/target/release/deps/libgimli-4a7f42e256b7913e.rlib","/build/dnp3/target/release/deps/libgimli-4a7f42e256b7913e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.17","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pin-project-lite-0.2.17/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pin_project_lite","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pin-project-lite-0.2.17/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpin_project_lite-810466feb861c31e.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpin_project_lite-810466feb861c31e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#clap_lex@1.1.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_lex-1.1.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"clap_lex","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_lex-1.1.0/src/lib.rs","edition":"2024","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libclap_lex-e38f1954cd59c843.rlib","/build/dnp3/target/release/deps/libclap_lex-e38f1954cd59c843.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#platforms@2.0.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/platforms-2.0.0/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/platforms-2.0.0/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/build/platforms-277c5ff807870cef/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rustc-demangle@0.1.27","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustc-demangle-0.1.27/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rustc_demangle","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustc-demangle-0.1.27/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/librustc_demangle-6a59aac61a06e0ef.rlib","/build/dnp3/target/release/deps/librustc_demangle-6a59aac61a06e0ef.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#base64ct@1.8.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/base64ct-1.8.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"base64ct","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/base64ct-1.8.3/src/lib.rs","edition":"2024","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbase64ct-c349615a7831b303.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbase64ct-c349615a7831b303.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cpufeatures@0.2.17","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cpufeatures-0.2.17/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cpufeatures","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cpufeatures-0.2.17/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcpufeatures-929461b872a5ccc6.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcpufeatures-929461b872a5ccc6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/itoa-1.0.18/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"itoa","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/itoa-1.0.18/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libitoa-7a4cbf85b66f6f98.rlib","/build/dnp3/target/release/deps/libitoa-7a4cbf85b66f6f98.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg-if-1.0.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cfg_if","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg-if-1.0.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libcfg_if-28021643dc2490eb.rlib","/build/dnp3/target/release/deps/libcfg_if-28021643dc2490eb.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.17","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pin-project-lite-0.2.17/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pin_project_lite","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pin-project-lite-0.2.17/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libpin_project_lite-3a4baeff80c5302d.rlib","/build/dnp3/target/release/deps/libpin_project_lite-3a4baeff80c5302d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/memchr-2.8.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"memchr","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/memchr-2.8.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmemchr-7aca204303c41f8a.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmemchr-7aca204303c41f8a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#semver@1.0.28","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/semver-1.0.28/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"semver","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/semver-1.0.28/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libsemver-3d112b812fea401c.rlib","/build/dnp3/target/release/deps/libsemver-3d112b812fea401c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-sink@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-sink-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_sink","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-sink-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_sink-73d9619ecc0a0389.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_sink-73d9619ecc0a0389.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#const-oid@0.9.6","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/const-oid-0.9.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"const_oid","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/const-oid-0.9.6/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libconst_oid-bb9af13a578d33cf.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libconst_oid-bb9af13a578d33cf.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#autocfg@1.5.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/autocfg-1.5.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"autocfg","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/autocfg-1.5.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libautocfg-da071fec8bb21226.rlib","/build/dnp3/target/release/deps/libautocfg-da071fec8bb21226.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-core-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-core-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_core-a7082f6d877ddcd4.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_core-a7082f6d877ddcd4.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.45/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"quote","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.45/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","proc-macro"],"filenames":["/build/dnp3/target/release/deps/libquote-6462f4c5c001e9d8.rlib","/build/dnp3/target/release/deps/libquote-6462f4c5c001e9d8.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#libc@0.2.185","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"libc","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/liblibc-771ee2d721970fc9.rlib","/build/dnp3/target/release/deps/liblibc-771ee2d721970fc9.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#typenum@1.19.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/typenum-1.19.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"typenum","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/typenum-1.19.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtypenum-85426667bb29b4de.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtypenum-85426667bb29b4de.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#libc@0.2.185","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"libc","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","extra_traits","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblibc-7aa287e1b53fba70.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblibc-7aa287e1b53fba70.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#anstyle-parse@1.0.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-parse-1.0.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"anstyle_parse","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-parse-1.0.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","utf8"],"filenames":["/build/dnp3/target/release/deps/libanstyle_parse-593540c538afddf9.rlib","/build/dnp3/target/release/deps/libanstyle_parse-593540c538afddf9.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#aho-corasick@1.1.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"aho_corasick","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["perf-literal","std"],"filenames":["/build/dnp3/target/release/deps/libaho_corasick-77defa4be01757f5.rlib","/build/dnp3/target/release/deps/libaho_corasick-77defa4be01757f5.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["result","std"],"filenames":["/build/dnp3/target/release/deps/libserde_core-5920ff8c9013a0f6.rlib","/build/dnp3/target/release/deps/libserde_core-5920ff8c9013a0f6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-core@0.1.36","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-core-0.1.36/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-core-0.1.36/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["once_cell","std"],"filenames":["/build/dnp3/target/release/deps/libtracing_core-a935839dcef5e16d.rlib","/build/dnp3/target/release/deps/libtracing_core-a935839dcef5e16d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#addr2line@0.25.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/addr2line-0.25.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"addr2line","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/addr2line-0.25.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libaddr2line-f290ebcd30e046fd.rlib","/build/dnp3/target/release/deps/libaddr2line-f290ebcd30e046fd.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#miniz_oxide@0.8.9","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/miniz_oxide-0.8.9/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"miniz_oxide","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/miniz_oxide-0.8.9/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libminiz_oxide-d6022a4640c802c8.rlib","/build/dnp3/target/release/deps/libminiz_oxide-d6022a4640c802c8.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pem-rfc7468@0.7.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pem-rfc7468-0.7.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pem_rfc7468","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pem-rfc7468-0.7.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpem_rfc7468-1fde0d11529dd55a.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpem_rfc7468-1fde0d11529dd55a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cfg_aliases@0.2.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg_aliases-0.2.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cfg_aliases","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg_aliases-0.2.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libcfg_aliases-eb1b10a1b3309217.rlib","/build/dnp3/target/release/deps/libcfg_aliases-eb1b10a1b3309217.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#lazy_static@1.5.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lazy_static-1.5.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"lazy_static","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lazy_static-1.5.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/liblazy_static-3059ee5ae6a8cc41.rlib","/build/dnp3/target/release/deps/liblazy_static-3059ee5ae6a8cc41.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rustls-pki-types@1.14.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-pki-types-1.14.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rustls_pki_types","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-pki-types-1.14.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librustls_pki_types-31db3f15d1e87c36.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librustls_pki_types-31db3f15d1e87c36.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-core@0.1.36","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-core-0.1.36/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-core-0.1.36/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","once_cell","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_core-82ef0b2b5d9ce9e7.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_core-82ef0b2b5d9ce9e7.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-channel@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-channel-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_channel","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-channel-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","futures-sink","sink","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_channel-6701040026dbdfe0.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_channel-6701040026dbdfe0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#num-traits@0.2.19","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/build/num-traits-d9b6f1fd82a543cd/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rustls@0.23.45","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.45/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.45/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["aws-lc-rs","aws_lc_rs","log","logging","std","tls12"],"filenames":["/build/dnp3/target/release/build/rustls-76ae4108d56294ee/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#bitflags@1.3.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bitflags-1.3.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"bitflags","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bitflags-1.3.2/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbitflags-f000714ba261c10e.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbitflags-f000714ba261c10e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-task@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-task-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_task","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-task-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_task-f6543aaa23fe99d3.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_task-f6543aaa23fe99d3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-io@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-io-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_io","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-io-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_io-374b7042d2c9975a.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_io-374b7042d2c9975a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#slab@0.4.12","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/slab-0.4.12/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"slab","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/slab-0.4.12/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libslab-a3aec08dfc33854e.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libslab-a3aec08dfc33854e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#untrusted@0.9.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/untrusted-0.9.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"untrusted","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/untrusted-0.9.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libuntrusted-65cbb5a2291a69c6.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libuntrusted-65cbb5a2291a69c6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#bitflags@2.11.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bitflags-2.11.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"bitflags","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bitflags-2.11.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbitflags-3ab978bdc6462f74.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbitflags-3ab978bdc6462f74.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#bytes@1.11.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.11.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"bytes","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.11.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbytes-1bafb44421458806.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbytes-1bafb44421458806.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#scopeguard@1.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scopeguard-1.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"scopeguard","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scopeguard-1.2.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","use_std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscopeguard-709824b4872089ef.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscopeguard-709824b4872089ef.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/build/serde-51f8cabc1e92e4be/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rand_core@0.6.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rand_core-0.6.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rand_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rand_core-0.6.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librand_core-4d09d55f4fd7128d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librand_core-4d09d55f4fd7128d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#iana-time-zone@0.1.65","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iana-time-zone-0.1.65/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"iana_time_zone","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iana-time-zone-0.1.65/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["fallback"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libiana_time_zone-96b6b12d923f1a62.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libiana_time_zone-96b6b12d923f1a62.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#base64@0.22.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/base64-0.22.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"base64","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/base64-0.22.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbase64-b8811b76be2877b0.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbase64-b8811b76be2877b0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rx509@0.2.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rx509-0.2.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rx509","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rx509-0.2.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librx509-1f28384b53d23d1d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librx509-1f28384b53d23d1d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#lazy_static@1.5.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lazy_static-1.5.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"lazy_static","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lazy_static-1.5.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblazy_static-6c465f40d154fe00.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblazy_static-6c465f40d154fe00.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/itoa-1.0.18/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"itoa","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/itoa-1.0.18/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libitoa-dde2abcaca5abe8c.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libitoa-dde2abcaca5abe8c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#thread_local@1.1.9","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thread_local-1.1.9/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"thread_local","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thread_local-1.1.9/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libthread_local-91eedfb3bbaa910e.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libthread_local-91eedfb3bbaa910e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#nu-ansi-term@0.50.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nu-ansi-term-0.50.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"nu_ansi_term","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nu-ansi-term-0.50.3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnu_ansi_term-f18bc27446c795e0.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnu_ansi_term-f18bc27446c795e0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#xxhash-rust@0.8.15","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/xxhash-rust-0.8.15/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"xxhash_rust","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/xxhash-rust-0.8.15/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["xxh64"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libxxhash_rust-f13c01620dfcf5a0.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libxxhash_rust-f13c01620dfcf5a0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#smallvec@1.15.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/smallvec-1.15.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"smallvec","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/smallvec-1.15.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsmallvec-7352a0982df94947.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsmallvec-7352a0982df94947.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#scursor@0.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scursor-0.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"scursor","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scursor-0.2.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscursor-5b5b156e044eee67.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscursor-5b5b156e044eee67.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sfio-promise@0.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-promise-0.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sfio_promise","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-promise-0.2.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsfio_promise-3bbf3f288fa4b841.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsfio_promise-3bbf3f288fa4b841.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/syn-2.0.117/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"syn","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/syn-2.0.117/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["clone-impls","default","derive","extra-traits","full","parsing","printing","proc-macro","visit-mut"],"filenames":["/build/dnp3/target/release/deps/libsyn-5fb96b0047a8d00b.rlib","/build/dnp3/target/release/deps/libsyn-5fb96b0047a8d00b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#generic-array@0.14.7","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"generic_array","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["more_lengths"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libgeneric_array-d865f073403721f1.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libgeneric_array-d865f073403721f1.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#jobserver@0.1.34","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/jobserver-0.1.34/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"jobserver","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/jobserver-0.1.34/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libjobserver-88778f603c9e3170.rlib","/build/dnp3/target/release/deps/libjobserver-88778f603c9e3170.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#anstream@1.0.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstream-1.0.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"anstream","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstream-1.0.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["auto","default","wincon"],"filenames":["/build/dnp3/target/release/deps/libanstream-f3a8feeed99a23cb.rlib","/build/dnp3/target/release/deps/libanstream-f3a8feeed99a23cb.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#regex-automata@0.4.14","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-automata-0.4.14/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"regex_automata","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-automata-0.4.14/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","dfa-onepass","hybrid","meta","nfa-backtrack","nfa-pikevm","nfa-thompson","perf-inline","perf-literal","perf-literal-multisubstring","perf-literal-substring","std","syntax","unicode","unicode-age","unicode-bool","unicode-case","unicode-gencat","unicode-perl","unicode-script","unicode-segment","unicode-word-boundary"],"filenames":["/build/dnp3/target/release/deps/libregex_automata-078445f3e0f0837f.rlib","/build/dnp3/target/release/deps/libregex_automata-078445f3e0f0837f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#object@0.37.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/object-0.37.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"object","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/object-0.37.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["archive","coff","elf","macho","pe","read_core","unaligned","xcoff"],"filenames":["/build/dnp3/target/release/deps/libobject-15b73b119d7e6c19.rlib","/build/dnp3/target/release/deps/libobject-15b73b119d7e6c19.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"zmij","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libzmij-534094fc2277839f.rlib","/build/dnp3/target/release/deps/libzmij-534094fc2277839f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#platforms@2.0.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/platforms-2.0.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"platforms","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/platforms-2.0.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libplatforms-e80f3a3d3e398e25.rlib","/build/dnp3/target/release/deps/libplatforms-e80f3a3d3e398e25.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#der@0.7.10","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/der-0.7.10/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"der","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/der-0.7.10/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","oid","pem","std","zeroize"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libder-de10fa2da9486bf5.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libder-de10fa2da9486bf5.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#mio@1.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/mio-1.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"mio","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/mio-1.2.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","log","net","os-ext","os-poll"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmio-7f36e802fc95a965.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmio-7f36e802fc95a965.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#nix@0.29.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.29.0/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.29.0/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","term"],"filenames":["/build/dnp3/target/release/build/nix-0c607e222c597047/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#socket2@0.6.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/socket2-0.6.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"socket2","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/socket2-0.6.3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["all"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsocket2-158d33b8c9af4d1b.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsocket2-158d33b8c9af4d1b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["result","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde_core-07165d9ae25357c3.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde_core-07165d9ae25357c3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#nix@0.26.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.26.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"nix","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.26.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["fs","ioctl","poll","process","signal","term"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnix-7c02514e7ca9d6a6.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnix-7c02514e7ca9d6a6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"zmij","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libzmij-84b4b84d7e563c3a.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libzmij-84b4b84d7e563c3a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pem@3.0.6","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pem-3.0.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pem","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pem-3.0.6/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpem-c9261c5440120518.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpem-c9261c5440120518.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-log@0.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-log-0.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing_log","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-log-0.2.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["log-tracer","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_log-e72fd1edaf8ad851.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_log-e72fd1edaf8ad851.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sharded-slab@0.1.7","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sharded-slab-0.1.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sharded_slab","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sharded-slab-0.1.7/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsharded_slab-ab41f9ced168e4cd.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsharded_slab-ab41f9ced168e4cd.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#num_cpus@1.17.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num_cpus-1.17.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"num_cpus","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num_cpus-1.17.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnum_cpus-c2d81ff4a539fff9.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnum_cpus-c2d81ff4a539fff9.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#crypto-common@0.1.7","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-common-0.1.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"crypto_common","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-common-0.1.7/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcrypto_common-9679b68da4f0e548.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcrypto_common-9679b68da4f0e548.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#thiserror-impl@2.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-impl-2.0.18/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"thiserror_impl","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-impl-2.0.18/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libthiserror_impl-6015b27eb24967d3.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cc@1.2.60","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cc-1.2.60/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cc","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cc-1.2.60/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["parallel"],"filenames":["/build/dnp3/target/release/deps/libcc-23a3c1d3cf528529.rlib","/build/dnp3/target/release/deps/libcc-23a3c1d3cf528529.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#block-padding@0.3.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-padding-0.3.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"block_padding","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-padding-0.3.3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libblock_padding-2fc88dc0097b833f.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libblock_padding-2fc88dc0097b833f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-attributes@0.1.31","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-attributes-0.1.31/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"tracing_attributes","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-attributes-0.1.31/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libtracing_attributes-e07a510e942fb0ba.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#block-buffer@0.10.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"block_buffer","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libblock_buffer-03f8f27e5f119e25.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libblock_buffer-03f8f27e5f119e25.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#clap_builder@4.6.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_builder-4.6.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"clap_builder","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_builder-4.6.0/src/lib.rs","edition":"2024","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["color","error-context","help","std","suggestions","usage"],"filenames":["/build/dnp3/target/release/deps/libclap_builder-43442bdfba6d37d3.rlib","/build/dnp3/target/release/deps/libclap_builder-43442bdfba6d37d3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_derive@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_derive-1.0.228/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"serde_derive","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_derive-1.0.228/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default"],"filenames":["/build/dnp3/target/release/deps/libserde_derive-efbe97b1aac3fb04.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#clap_derive@4.6.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_derive-4.6.1/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"clap_derive","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_derive-4.6.1/src/lib.rs","edition":"2024","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default"],"filenames":["/build/dnp3/target/release/deps/libclap_derive-27ecf755bbbf1c26.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#regex@1.12.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-1.12.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"regex","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-1.12.3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","perf","perf-backtrack","perf-cache","perf-dfa","perf-inline","perf-literal","perf-onepass","std","unicode","unicode-age","unicode-bool","unicode-case","unicode-gencat","unicode-perl","unicode-script","unicode-segment"],"filenames":["/build/dnp3/target/release/deps/libregex-8ffde440f03af825.rlib","/build/dnp3/target/release/deps/libregex-8ffde440f03af825.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#backtrace@0.3.76","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/backtrace-0.3.76/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"backtrace","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/backtrace-0.3.76/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libbacktrace-baaf37a236598424.rlib","/build/dnp3/target/release/deps/libbacktrace-baaf37a236598424.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde_json","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libserde_json-d2e34e61967fb2ba.rlib","/build/dnp3/target/release/deps/libserde_json-d2e34e61967fb2ba.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-macro@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-macro-0.3.32/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"futures_macro","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-macro-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libfutures_macro-571b160132d0a57d.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tokio-macros@2.7.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-macros-2.7.0/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"tokio_macros","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-macros-2.7.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libtokio_macros-6b3bd1dac3dd39ab.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#spki@0.7.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spki-0.7.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"spki","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spki-0.7.3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","pem","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libspki-573b800b49943744.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libspki-573b800b49943744.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#num-traits@0.2.19","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"num_traits","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnum_traits-8c1f986c2103613d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnum_traits-8c1f986c2103613d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde-9ff2552f4a980ede.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde-9ff2552f4a980ede.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde_json","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde_json-9f6410fc50d8ea84.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde_json-9f6410fc50d8ea84.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cmake@0.1.58","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cmake-0.1.58/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cmake","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cmake-0.1.58/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libcmake-29cd06496040dcd6.rlib","/build/dnp3/target/release/deps/libcmake-29cd06496040dcd6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#inout@0.1.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/inout-0.1.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"inout","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/inout-0.1.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["block-padding"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libinout-404802b1e1036e8d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libinout-404802b1e1036e8d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#digest@0.10.7","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"digest","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["block-buffer","core-api","default","mac","subtle"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libdigest-5922d1be4fa8657d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libdigest-5922d1be4fa8657d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","derive","serde_derive","std"],"filenames":["/build/dnp3/target/release/deps/libserde-446a2d07d006ea70.rlib","/build/dnp3/target/release/deps/libserde-446a2d07d006ea70.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#clap@4.6.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap-4.6.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"clap","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap-4.6.1/src/lib.rs","edition":"2024","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["color","default","derive","error-context","help","std","suggestions","usage"],"filenames":["/build/dnp3/target/release/deps/libclap-d2c57e3c24a11cf4.rlib","/build/dnp3/target/release/deps/libclap-d2c57e3c24a11cf4.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"thiserror","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libthiserror-05cf950e48f3f308.rlib","/build/dnp3/target/release/deps/libthiserror-05cf950e48f3f308.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-0.1.44/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-0.1.44/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["attributes","default","std","tracing-attributes"],"filenames":["/build/dnp3/target/release/deps/libtracing-ea3fdfbe4af6faea.rlib","/build/dnp3/target/release/deps/libtracing-ea3fdfbe4af6faea.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"thiserror","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libthiserror-9e714939f5b7af64.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libthiserror-9e714939f5b7af64.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-util@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-util-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_util","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-util-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","async-await","async-await-macro","channel","futures-channel","futures-io","futures-macro","futures-sink","io","memchr","sink","slab","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_util-4199551f783914da.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_util-4199551f783914da.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tokio@1.52.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.52.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tokio","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.52.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["bytes","default","io-std","io-util","libc","macros","mio","net","rt","rt-multi-thread","socket2","sync","time","tokio-macros"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio-52c4c55fe9d3605b.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio-52c4c55fe9d3605b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#nix@0.29.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.29.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"nix","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.29.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","term"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnix-e06722d453f9107d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnix-e06722d453f9107d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#chrono@0.4.44","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"chrono","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","clock","default","iana-time-zone","js-sys","now","oldtime","std","wasm-bindgen","wasmbind","winapi","windows-link"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libchrono-599bb9ad7de9cc61.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libchrono-599bb9ad7de9cc61.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-0.1.44/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-0.1.44/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["attributes","default","std","tracing-attributes"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing-4ca4880ee0c721ca.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing-4ca4880ee0c721ca.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-serde@0.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-serde-0.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing_serde","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-serde-0.2.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_serde-4bb271aa612b1563.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_serde-4bb271aa612b1563.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#aws-lc-sys@0.45.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-sys-0.45.0/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-main","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-sys-0.45.0/builder/main.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["prebuilt-nasm"],"filenames":["/build/dnp3/target/release/build/aws-lc-sys-91feda25585aba23/build-script-main"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cipher@0.4.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cipher-0.4.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cipher","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cipher-0.4.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["block-padding"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcipher-6817574d857e43e0.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcipher-6817574d857e43e0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#hmac@0.12.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hmac-0.12.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"hmac","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hmac-0.12.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libhmac-a2076952c48b3f77.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libhmac-a2076952c48b3f77.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#oo-bindgen@0.8.8","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/oo-bindgen-0.8.8/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"oo_bindgen","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/oo-bindgen-0.8.8/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/liboo_bindgen-89461f1f4d077926.rlib","/build/dnp3/target/release/deps/liboo_bindgen-89461f1f4d077926.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sha2@0.10.9","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sha2-0.10.9/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sha2","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sha2-0.10.9/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsha2-87ac78cfadeda05d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsha2-87ac78cfadeda05d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#unescaper@0.1.8","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/unescaper-0.1.8/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"unescaper","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/unescaper-0.1.8/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libunescaper-6e0589f217e3009c.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libunescaper-6e0589f217e3009c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-executor@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-executor-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_executor","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-executor-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_executor-e7c81904d84f37f6.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_executor-e7c81904d84f37f6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-subscriber@0.3.23","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-subscriber-0.3.23/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing_subscriber","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-subscriber-0.3.23/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","ansi","chrono","default","fmt","json","nu-ansi-term","registry","serde","serde_json","sharded-slab","smallvec","std","thread_local","tracing-log","tracing-serde"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_subscriber-cdf73b24c9181685.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_subscriber-cdf73b24c9181685.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pbkdf2@0.12.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pbkdf2-0.12.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pbkdf2","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pbkdf2-0.12.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","hmac"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpbkdf2-17a4c0874b25ecdf.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpbkdf2-17a4c0874b25ecdf.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#salsa20@0.10.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/salsa20-0.10.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"salsa20","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/salsa20-0.10.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsalsa20-b608be23fb6d77ef.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsalsa20-b608be23fb6d77ef.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cbc@0.1.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cbc-0.1.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cbc","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cbc-0.1.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["block-padding","default"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcbc-6132f6e9c72a2714.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcbc-6132f6e9c72a2714.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#aes@0.8.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aes-0.8.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"aes","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aes-0.8.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libaes-d63f74f7f5c343ff.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libaes-d63f74f7f5c343ff.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sfio-tokio-ffi@0.9.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-tokio-ffi-0.9.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sfio_tokio_ffi","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-tokio-ffi-0.9.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libsfio_tokio_ffi-cc8f0b58d98700db.rlib","/build/dnp3/target/release/deps/libsfio_tokio_ffi-cc8f0b58d98700db.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sfio-tracing-ffi@0.9.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-tracing-ffi-0.9.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sfio_tracing_ffi","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-tracing-ffi-0.9.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libsfio_tracing_ffi-c2c5dfa04769fc4b.rlib","/build/dnp3/target/release/deps/libsfio_tracing_ffi-c2c5dfa04769fc4b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serialport@4.9.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serialport-4.9.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serialport","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serialport-4.9.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserialport-fe71e642ec3210db.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserialport-fe71e642ec3210db.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","async-await","default","executor","futures-executor","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures-5a3a901221140d3c.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures-5a3a901221140d3c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#aws-lc-sys@0.45.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-sys-0.45.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"aws_lc_sys","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-sys-0.45.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["prebuilt-nasm"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libaws_lc_sys-37775763c8d75e31.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libaws_lc_sys-37775763c8d75e31.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#scrypt@0.11.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scrypt-0.11.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"scrypt","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scrypt-0.11.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscrypt-824ed7f357740171.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscrypt-824ed7f357740171.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#mio-serial@5.0.6","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/mio-serial-5.0.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"mio_serial","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/mio-serial-5.0.6/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmio_serial-264dc879ebc68924.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmio_serial-264dc879ebc68924.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"path+file:///build/dnp3/ffi/dnp3-schema#1.7.0","manifest_path":"/build/dnp3/ffi/dnp3-schema/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"dnp3_schema","src_path":"/build/dnp3/ffi/dnp3-schema/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libdnp3_schema-42f72463ebfdf796.rlib","/build/dnp3/target/release/deps/libdnp3_schema-42f72463ebfdf796.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#aws-lc-rs@1.18.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-rs-1.18.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"aws_lc_rs","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-rs-1.18.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["aws-lc-sys","prebuilt-nasm"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libaws_lc_rs-9c63bcb41c809423.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libaws_lc_rs-9c63bcb41c809423.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pkcs5@0.7.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkcs5-0.7.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pkcs5","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkcs5-0.7.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","pbes2"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpkcs5-01694de4ef65ac91.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpkcs5-01694de4ef65ac91.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tokio-serial@5.4.5","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-serial-5.4.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tokio_serial","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-serial-5.4.5/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio_serial-dc236905d7ed18d6.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio_serial-dc236905d7ed18d6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"path+file:///build/dnp3/ffi/dnp3-ffi#1.7.0","manifest_path":"/build/dnp3/ffi/dnp3-ffi/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/build/dnp3/ffi/dnp3-ffi/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["enable-tls","serial","tls-aws-lc"],"filenames":["/build/dnp3/target/release/build/dnp3-ffi-4f000ee6ed952640/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rustls-webpki@0.103.15","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-webpki-0.103.15/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"webpki","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-webpki-0.103.15/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","aws-lc-rs","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libwebpki-5f264d779ee8b0a2.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libwebpki-5f264d779ee8b0a2.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pkcs8@0.10.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkcs8-0.10.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pkcs8","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkcs8-0.10.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","encryption","pem","pkcs5","rand_core","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpkcs8-456c60df3aa91c68.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpkcs8-456c60df3aa91c68.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rustls@0.23.45","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.45/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rustls","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.45/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["aws-lc-rs","aws_lc_rs","log","logging","std","tls12"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librustls-2a56832588df99dd.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librustls-2a56832588df99dd.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sfio-rustls-config@0.4.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-rustls-config-0.4.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sfio_rustls_config","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-rustls-config-0.4.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["crypto-aws-lc","default"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsfio_rustls_config-0029d3a360c93691.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsfio_rustls_config-0029d3a360c93691.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tokio-rustls@0.26.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-rustls-0.26.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tokio_rustls","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-rustls-0.26.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["tls12"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio_rustls-34ef08b894db820e.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio_rustls-34ef08b894db820e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"path+file:///build/dnp3/dnp3#1.7.0","manifest_path":"/build/dnp3/dnp3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"dnp3","src_path":"/build/dnp3/dnp3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["enable-tls","ffi","serial","sfio-rustls-config","tls-aws-lc","tokio-rustls","tokio-serial"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libdnp3-9e19127af7cbe2cd.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libdnp3-9e19127af7cbe2cd.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"path+file:///build/dnp3/ffi/dnp3-ffi#1.7.0","manifest_path":"/build/dnp3/ffi/dnp3-ffi/Cargo.toml","target":{"kind":["rlib","cdylib"],"crate_types":["rlib","cdylib"],"name":"dnp3_ffi","src_path":"/build/dnp3/ffi/dnp3-ffi/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["enable-tls","serial","tls-aws-lc"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/libdnp3_ffi.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/libdnp3_ffi.so"],"executable":null,"fresh":true} +{"reason":"build-finished","success":true} diff --git a/allow-list/tests/fixtures/dnp3/targets/aws/runtime-tree.txt b/allow-list/tests/fixtures/dnp3/targets/aws/runtime-tree.txt new file mode 100644 index 0000000..e8ed1ad --- /dev/null +++ b/allow-list/tests/fixtures/dnp3/targets/aws/runtime-tree.txt @@ -0,0 +1,159 @@ +0dnp3-ffi v1.7.0 (/build/dnp3/ffi/dnp3-ffi)|enable-tls,serial,tls-aws-lc +1dnp3 v1.7.0 (/build/dnp3/dnp3)|enable-tls,ffi,serial,sfio-rustls-config,tls-aws-lc,tokio-rustls,tokio-serial +2chrono v0.4.44|alloc,clock,default,iana-time-zone,js-sys,now,oldtime,std,wasm-bindgen,wasmbind,winapi,windows-link +3iana-time-zone v0.1.65|fallback +3num-traits v0.2.19| +2scursor v0.2.0| +2sfio-rustls-config v0.4.0|crypto-aws-lc,default +3pem v3.0.6|default,std +4base64 v0.22.1|alloc,std +3pkcs8 v0.10.2|alloc,encryption,pem,pkcs5,rand_core,std +4der v0.7.10|alloc,oid,pem,std,zeroize +5const-oid v0.9.6| +5pem-rfc7468 v0.7.0|alloc +6base64ct v1.8.3|alloc +5zeroize v1.8.2|alloc,default +4pkcs5 v0.7.1|alloc,pbes2 +5aes v0.8.4| +6cfg-if v1.0.4| +6cipher v0.4.4|block-padding +7crypto-common v0.1.7| +8generic-array v0.14.7|more_lengths +9typenum v1.19.0| +8typenum v1.19.0| +7inout v0.1.4|block-padding +8block-padding v0.3.3| +9generic-array v0.14.7|more_lengths (*) +8generic-array v0.14.7|more_lengths (*) +6cpufeatures v0.2.17| +5cbc v0.1.2|block-padding,default +6cipher v0.4.4|block-padding (*) +5der v0.7.10|alloc,oid,pem,std,zeroize (*) +5pbkdf2 v0.12.2|default,hmac +6digest v0.10.7|block-buffer,core-api,default,mac,subtle +7block-buffer v0.10.4| +8generic-array v0.14.7|more_lengths (*) +7crypto-common v0.1.7| (*) +7subtle v2.6.1| +6hmac v0.12.1| +7digest v0.10.7|block-buffer,core-api,default,mac,subtle (*) +5scrypt v0.11.0| +6pbkdf2 v0.12.2|default,hmac (*) +6salsa20 v0.10.2| +7cipher v0.4.4|block-padding (*) +6sha2 v0.10.9| +7cfg-if v1.0.4| +7cpufeatures v0.2.17| +7digest v0.10.7|block-buffer,core-api,default,mac,subtle (*) +5sha2 v0.10.9| (*) +5spki v0.7.3|alloc,pem,std +6der v0.7.10|alloc,oid,pem,std,zeroize (*) +4rand_core v0.6.4| +4spki v0.7.3|alloc,pem,std (*) +3rustls v0.23.45|aws-lc-rs,aws_lc_rs,log,logging,std,tls12 +4aws-lc-rs v1.18.1|aws-lc-sys,prebuilt-nasm +5aws-lc-sys v0.45.0|prebuilt-nasm +5zeroize v1.8.2|alloc,default +4log v0.4.29|std +4once_cell v1.21.4|alloc,default,race,std +4rustls-pki-types v1.14.0|alloc,default,std +5zeroize v1.8.2|alloc,default +4rustls-webpki v0.103.15|alloc,aws-lc-rs,std +5aws-lc-rs v1.18.1|aws-lc-sys,prebuilt-nasm (*) +5rustls-pki-types v1.14.0|alloc,default,std (*) +5untrusted v0.9.0| +4subtle v2.6.1| +4zeroize v1.8.2|alloc,default +3rustls-pki-types v1.14.0|alloc,default,std (*) +3rustls-webpki v0.103.15|alloc,aws-lc-rs,std (*) +3rx509 v0.2.1| +2tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros +3bytes v1.11.1|default,std +3libc v0.2.185|default,extra_traits,std +3mio v1.2.0|default,log,net,os-ext,os-poll +4libc v0.2.185|default,extra_traits,std +4log v0.4.29|std +3pin-project-lite v0.2.17| +3socket2 v0.6.3|all +4libc v0.2.185|default,extra_traits,std +2tokio-rustls v0.26.4|tls12 +3rustls v0.23.45|aws-lc-rs,aws_lc_rs,log,logging,std,tls12 (*) +3tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +2tokio-serial v5.4.5| +3cfg-if v1.0.4| +3futures v0.3.32|alloc,async-await,default,executor,futures-executor,std +4futures-channel v0.3.32|alloc,futures-sink,sink,std +5futures-core v0.3.32|alloc,std +5futures-sink v0.3.32|alloc,std +4futures-core v0.3.32|alloc,std +4futures-executor v0.3.32|std +5futures-core v0.3.32|alloc,std +5futures-task v0.3.32|alloc,std +5futures-util v0.3.32|alloc,async-await,async-await-macro,channel,futures-channel,futures-io,futures-macro,futures-sink,io,memchr,sink,slab,std +6futures-channel v0.3.32|alloc,futures-sink,sink,std (*) +6futures-core v0.3.32|alloc,std +6futures-io v0.3.32|std +6futures-sink v0.3.32|alloc,std +6futures-task v0.3.32|alloc,std +6memchr v2.8.0|alloc,default,std +6pin-project-lite v0.2.17| +6slab v0.4.12|std +4futures-io v0.3.32|std +4futures-sink v0.3.32|alloc,std +4futures-task v0.3.32|alloc,std +4futures-util v0.3.32|alloc,async-await,async-await-macro,channel,futures-channel,futures-io,futures-macro,futures-sink,io,memchr,sink,slab,std (*) +3log v0.4.29|std +3mio-serial v5.0.6| +4log v0.4.29|std +4mio v1.2.0|default,log,net,os-ext,os-poll (*) +4nix v0.29.0|default,term +5bitflags v2.11.1| +5cfg-if v1.0.4| +5libc v0.2.185|default,extra_traits,std +4serialport v4.9.0| +5bitflags v2.11.1| +5cfg-if v1.0.4| +5nix v0.26.4|fs,ioctl,poll,process,signal,term +6bitflags v1.3.2|default +6cfg-if v1.0.4| +6libc v0.2.185|default,extra_traits,std +5scopeguard v1.2.0|default,use_std +5unescaper v0.1.8| +6thiserror v2.0.18|default,std +3serialport v4.9.0| (*) +3tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +2tracing v0.1.44|attributes,default,std,tracing-attributes +3pin-project-lite v0.2.17| +3tracing-core v0.1.36|default,once_cell,std +4once_cell v1.21.4|alloc,default,race,std +2xxhash-rust v0.8.15|xxh64 +1lazy_static v1.5.0| +1num_cpus v1.17.0| +2libc v0.2.185|default,extra_traits,std +1sfio-promise v0.2.0| +1tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +1tracing v0.1.44|attributes,default,std,tracing-attributes (*) +1tracing-core v0.1.36|default,once_cell,std (*) +1tracing-subscriber v0.3.23|alloc,ansi,chrono,default,fmt,json,nu-ansi-term,registry,serde,serde_json,sharded-slab,smallvec,std,thread_local,tracing-log,tracing-serde +2chrono v0.4.44|alloc,clock,default,iana-time-zone,js-sys,now,oldtime,std,wasm-bindgen,wasmbind,winapi,windows-link (*) +2nu-ansi-term v0.50.3|default,std +2serde v1.0.228|default,std +3serde_core v1.0.228|result,std +2serde_json v1.0.149|default,std +3itoa v1.0.18| +3memchr v2.8.0|alloc,default,std +3serde_core v1.0.228|result,std +3zmij v1.0.21| +2sharded-slab v0.1.7| +3lazy_static v1.5.0| +2smallvec v1.15.1| +2thread_local v1.1.9| +3cfg-if v1.0.4| +2tracing-core v0.1.36|default,once_cell,std (*) +2tracing-log v0.2.0|log-tracer,std +3log v0.4.29|std +3once_cell v1.21.4|alloc,default,race,std +3tracing-core v0.1.36|default,once_cell,std (*) +2tracing-serde v0.2.0| +3serde v1.0.228|default,std (*) +3tracing-core v0.1.36|default,once_cell,std (*) diff --git a/allow-list/tests/fixtures/dnp3/targets/aws/tree.txt b/allow-list/tests/fixtures/dnp3/targets/aws/tree.txt new file mode 100644 index 0000000..6c7f152 --- /dev/null +++ b/allow-list/tests/fixtures/dnp3/targets/aws/tree.txt @@ -0,0 +1,263 @@ +0dnp3-ffi v1.7.0 (/build/dnp3/ffi/dnp3-ffi)|enable-tls,serial,tls-aws-lc +1dnp3 v1.7.0 (/build/dnp3/dnp3)|enable-tls,ffi,serial,sfio-rustls-config,tls-aws-lc,tokio-rustls,tokio-serial +2chrono v0.4.44|alloc,clock,default,iana-time-zone,js-sys,now,oldtime,std,wasm-bindgen,wasmbind,winapi,windows-link +3iana-time-zone v0.1.65|fallback +3num-traits v0.2.19| +4autocfg v1.5.0| +2scursor v0.2.0| +2sfio-rustls-config v0.4.0|crypto-aws-lc,default +3pem v3.0.6|default,std +4base64 v0.22.1|alloc,std +3pkcs8 v0.10.2|alloc,encryption,pem,pkcs5,rand_core,std +4der v0.7.10|alloc,oid,pem,std,zeroize +5const-oid v0.9.6| +5pem-rfc7468 v0.7.0|alloc +6base64ct v1.8.3|alloc +5zeroize v1.8.2|alloc,default +4pkcs5 v0.7.1|alloc,pbes2 +5aes v0.8.4| +6cfg-if v1.0.4| +6cipher v0.4.4|block-padding +7crypto-common v0.1.7| +8generic-array v0.14.7|more_lengths +9typenum v1.19.0| +9version_check v0.9.5| +8typenum v1.19.0| +7inout v0.1.4|block-padding +8block-padding v0.3.3| +9generic-array v0.14.7|more_lengths (*) +8generic-array v0.14.7|more_lengths (*) +6cpufeatures v0.2.17| +5cbc v0.1.2|block-padding,default +6cipher v0.4.4|block-padding (*) +5der v0.7.10|alloc,oid,pem,std,zeroize (*) +5pbkdf2 v0.12.2|default,hmac +6digest v0.10.7|block-buffer,core-api,default,mac,subtle +7block-buffer v0.10.4| +8generic-array v0.14.7|more_lengths (*) +7crypto-common v0.1.7| (*) +7subtle v2.6.1| +6hmac v0.12.1| +7digest v0.10.7|block-buffer,core-api,default,mac,subtle (*) +5scrypt v0.11.0| +6pbkdf2 v0.12.2|default,hmac (*) +6salsa20 v0.10.2| +7cipher v0.4.4|block-padding (*) +6sha2 v0.10.9| +7cfg-if v1.0.4| +7cpufeatures v0.2.17| +7digest v0.10.7|block-buffer,core-api,default,mac,subtle (*) +5sha2 v0.10.9| (*) +5spki v0.7.3|alloc,pem,std +6der v0.7.10|alloc,oid,pem,std,zeroize (*) +4rand_core v0.6.4| +4spki v0.7.3|alloc,pem,std (*) +3rustls v0.23.45|aws-lc-rs,aws_lc_rs,log,logging,std,tls12 +4aws-lc-rs v1.18.1|aws-lc-sys,prebuilt-nasm +5aws-lc-sys v0.45.0|prebuilt-nasm +6cc v1.2.60|parallel +7find-msvc-tools v0.1.9| +7jobserver v0.1.34| +8libc v0.2.185|default,std +7libc v0.2.185|default,std +7shlex v1.3.0|default,std +6cmake v0.1.58| +7cc v1.2.60|parallel (*) +6dunce v1.0.5| +6fs_extra v1.3.0| +6pkg-config v0.3.34| +5zeroize v1.8.2|alloc,default +4log v0.4.29|std +4once_cell v1.21.4|alloc,default,race,std +4rustls-pki-types v1.14.0|alloc,default,std +5zeroize v1.8.2|alloc,default +4rustls-webpki v0.103.15|alloc,aws-lc-rs,std +5aws-lc-rs v1.18.1|aws-lc-sys,prebuilt-nasm (*) +5rustls-pki-types v1.14.0|alloc,default,std (*) +5untrusted v0.9.0| +4subtle v2.6.1| +4zeroize v1.8.2|alloc,default +3rustls-pki-types v1.14.0|alloc,default,std (*) +3rustls-webpki v0.103.15|alloc,aws-lc-rs,std (*) +3rx509 v0.2.1| +2tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros +3bytes v1.11.1|default,std +3libc v0.2.185|default,extra_traits,std +3mio v1.2.0|default,log,net,os-ext,os-poll +4libc v0.2.185|default,extra_traits,std +4log v0.4.29|std +3pin-project-lite v0.2.17| +3socket2 v0.6.3|all +4libc v0.2.185|default,extra_traits,std +3tokio-macros v2.7.0 (proc-macro)| +4proc-macro2 v1.0.106|default,proc-macro +5unicode-ident v1.0.24| +4quote v1.0.45|default,proc-macro +5proc-macro2 v1.0.106|default,proc-macro (*) +4syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut +5proc-macro2 v1.0.106|default,proc-macro (*) +5quote v1.0.45|default,proc-macro (*) +5unicode-ident v1.0.24| +2tokio-rustls v0.26.4|tls12 +3rustls v0.23.45|aws-lc-rs,aws_lc_rs,log,logging,std,tls12 (*) +3tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +2tokio-serial v5.4.5| +3cfg-if v1.0.4| +3futures v0.3.32|alloc,async-await,default,executor,futures-executor,std +4futures-channel v0.3.32|alloc,futures-sink,sink,std +5futures-core v0.3.32|alloc,std +5futures-sink v0.3.32|alloc,std +4futures-core v0.3.32|alloc,std +4futures-executor v0.3.32|std +5futures-core v0.3.32|alloc,std +5futures-task v0.3.32|alloc,std +5futures-util v0.3.32|alloc,async-await,async-await-macro,channel,futures-channel,futures-io,futures-macro,futures-sink,io,memchr,sink,slab,std +6futures-channel v0.3.32|alloc,futures-sink,sink,std (*) +6futures-core v0.3.32|alloc,std +6futures-io v0.3.32|std +6futures-macro v0.3.32 (proc-macro)| +7proc-macro2 v1.0.106|default,proc-macro (*) +7quote v1.0.45|default,proc-macro (*) +7syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut (*) +6futures-sink v0.3.32|alloc,std +6futures-task v0.3.32|alloc,std +6memchr v2.8.0|alloc,default,std +6pin-project-lite v0.2.17| +6slab v0.4.12|std +4futures-io v0.3.32|std +4futures-sink v0.3.32|alloc,std +4futures-task v0.3.32|alloc,std +4futures-util v0.3.32|alloc,async-await,async-await-macro,channel,futures-channel,futures-io,futures-macro,futures-sink,io,memchr,sink,slab,std (*) +3log v0.4.29|std +3mio-serial v5.0.6| +4log v0.4.29|std +4mio v1.2.0|default,log,net,os-ext,os-poll (*) +4nix v0.29.0|default,term +5bitflags v2.11.1| +5cfg-if v1.0.4| +5libc v0.2.185|default,extra_traits,std +5cfg_aliases v0.2.1| +4serialport v4.9.0| +5bitflags v2.11.1| +5cfg-if v1.0.4| +5nix v0.26.4|fs,ioctl,poll,process,signal,term +6bitflags v1.3.2|default +6cfg-if v1.0.4| +6libc v0.2.185|default,extra_traits,std +5scopeguard v1.2.0|default,use_std +5unescaper v0.1.8| +6thiserror v2.0.18|default,std +7thiserror-impl v2.0.18 (proc-macro)| +8proc-macro2 v1.0.106|default,proc-macro (*) +8quote v1.0.45|default,proc-macro (*) +8syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut (*) +3serialport v4.9.0| (*) +3tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +2tracing v0.1.44|attributes,default,std,tracing-attributes +3pin-project-lite v0.2.17| +3tracing-attributes v0.1.31 (proc-macro)| +4proc-macro2 v1.0.106|default,proc-macro (*) +4quote v1.0.45|default,proc-macro (*) +4syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut (*) +3tracing-core v0.1.36|default,once_cell,std +4once_cell v1.21.4|alloc,default,race,std +2xxhash-rust v0.8.15|xxh64 +1lazy_static v1.5.0| +1num_cpus v1.17.0| +2libc v0.2.185|default,extra_traits,std +1sfio-promise v0.2.0| +1tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +1tracing v0.1.44|attributes,default,std,tracing-attributes (*) +1tracing-core v0.1.36|default,once_cell,std (*) +1tracing-subscriber v0.3.23|alloc,ansi,chrono,default,fmt,json,nu-ansi-term,registry,serde,serde_json,sharded-slab,smallvec,std,thread_local,tracing-log,tracing-serde +2chrono v0.4.44|alloc,clock,default,iana-time-zone,js-sys,now,oldtime,std,wasm-bindgen,wasmbind,winapi,windows-link (*) +2nu-ansi-term v0.50.3|default,std +2serde v1.0.228|default,std +3serde_core v1.0.228|result,std +2serde_json v1.0.149|default,std +3itoa v1.0.18| +3memchr v2.8.0|alloc,default,std +3serde_core v1.0.228|result,std +3zmij v1.0.21| +2sharded-slab v0.1.7| +3lazy_static v1.5.0| +2smallvec v1.15.1| +2thread_local v1.1.9| +3cfg-if v1.0.4| +2tracing-core v0.1.36|default,once_cell,std (*) +2tracing-log v0.2.0|log-tracer,std +3log v0.4.29|std +3once_cell v1.21.4|alloc,default,race,std +3tracing-core v0.1.36|default,once_cell,std (*) +2tracing-serde v0.2.0| +3serde v1.0.228|default,std (*) +3tracing-core v0.1.36|default,once_cell,std (*) +1dnp3-schema v1.7.0 (/build/dnp3/ffi/dnp3-schema)| +2oo-bindgen v0.8.8| +3backtrace v0.3.76|default,std +4addr2line v0.25.1| +5gimli v0.32.3|read,read-core +4cfg-if v1.0.4| +4libc v0.2.185|default,std +4miniz_oxide v0.8.9| +5adler2 v2.0.1| +4object v0.37.3|archive,coff,elf,macho,pe,read_core,unaligned,xcoff +5memchr v2.8.0|alloc,std +4rustc-demangle v0.1.27| +3clap v4.6.1|color,default,derive,error-context,help,std,suggestions,usage +4clap_builder v4.6.0|color,error-context,help,std,suggestions,usage +5anstream v1.0.0|auto,default,wincon +6anstyle v1.0.14|default,std +6anstyle-parse v1.0.0|default,utf8 +7utf8parse v0.2.2|default +6anstyle-query v1.1.5| +6colorchoice v1.0.5| +6is_terminal_polyfill v1.70.2|default +6utf8parse v0.2.2|default +5anstyle v1.0.14|default,std +5clap_lex v1.1.0| +5strsim v0.11.1| +4clap_derive v4.6.1 (proc-macro)|default +5heck v0.5.0| +5proc-macro2 v1.0.106|default,proc-macro (*) +5quote v1.0.45|default,proc-macro (*) +5syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut (*) +3dunce v1.0.5| +3heck v0.5.0| +3lazy_static v1.5.0| +3platforms v2.0.0|default,std +3regex v1.12.3|default,perf,perf-backtrack,perf-cache,perf-dfa,perf-inline,perf-literal,perf-onepass,std,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment +4aho-corasick v1.1.4|perf-literal,std +5memchr v2.8.0|alloc,std +4memchr v2.8.0|alloc,std +4regex-automata v0.4.14|alloc,dfa-onepass,hybrid,meta,nfa-backtrack,nfa-pikevm,nfa-thompson,perf-inline,perf-literal,perf-literal-multisubstring,perf-literal-substring,std,syntax,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment,unicode-word-boundary +5aho-corasick v1.1.4|perf-literal,std (*) +5memchr v2.8.0|alloc,std +5regex-syntax v0.8.10|default,std,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment +4regex-syntax v0.8.10|default,std,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment +3semver v1.0.28|default,std +3serde v1.0.228|default,derive,serde_derive,std +4serde_core v1.0.228|result,std +4serde_derive v1.0.228 (proc-macro)|default +5proc-macro2 v1.0.106|default,proc-macro (*) +5quote v1.0.45|default,proc-macro (*) +5syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut (*) +3serde_json v1.0.149|default,std +4itoa v1.0.18| +4memchr v2.8.0|alloc,std +4serde_core v1.0.228|result,std +4zmij v1.0.21| +3thiserror v2.0.18|default,std +4thiserror-impl v2.0.18 (proc-macro)| (*) +3tracing v0.1.44|attributes,default,std,tracing-attributes +4pin-project-lite v0.2.17| +4tracing-attributes v0.1.31 (proc-macro)| (*) +4tracing-core v0.1.36|once_cell,std +5once_cell v1.21.4|alloc,default,race,std +2sfio-tokio-ffi v0.9.0| +3oo-bindgen v0.8.8| (*) +2sfio-tracing-ffi v0.9.0| +3oo-bindgen v0.8.8| (*) +1oo-bindgen v0.8.8| (*) +1sfio-tokio-ffi v0.9.0| (*) +1sfio-tracing-ffi v0.9.0| (*) diff --git a/allow-list/tests/fixtures/dnp3/targets/ring/build.json b/allow-list/tests/fixtures/dnp3/targets/ring/build.json new file mode 100644 index 0000000..208538b --- /dev/null +++ b/allow-list/tests/fixtures/dnp3/targets/ring/build.json @@ -0,0 +1,170 @@ +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/proc-macro2-1.0.106/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/proc-macro2-1.0.106/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","proc-macro"],"filenames":["/build/dnp3/target/release/build/proc-macro2-986587f949cb3616/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.45/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.45/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","proc-macro"],"filenames":["/build/dnp3/target/release/build/quote-c93d442eb9933478/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.24","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/unicode-ident-1.0.24/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"unicode_ident","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/unicode-ident-1.0.24/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libunicode_ident-eb594fc5b763ee92.rlib","/build/dnp3/target/release/deps/libunicode_ident-eb594fc5b763ee92.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#version_check@0.9.5","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/version_check-0.9.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"version_check","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/version_check-0.9.5/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libversion_check-23278575be3c0f59.rlib","/build/dnp3/target/release/deps/libversion_check-23278575be3c0f59.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#typenum@1.19.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/typenum-1.19.0/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/typenum-1.19.0/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/build/typenum-b8d3f63d8a932f1e/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg-if-1.0.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cfg_if","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg-if-1.0.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcfg_if-3a5641228175f401.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcfg_if-3a5641228175f401.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#libc@0.2.185","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","extra_traits","std"],"filenames":["/build/dnp3/target/release/build/libc-d94ce3dda6b693b5/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["result","std"],"filenames":["/build/dnp3/target/release/build/serde_core-e52075bc2b27c91d/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/build/thiserror-c2e697b5955ec78e/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/build/zmij-6b72ac5b6722cab2/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/memchr-2.8.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"memchr","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/memchr-2.8.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","std"],"filenames":["/build/dnp3/target/release/deps/libmemchr-0b36fee4e09e12a3.rlib","/build/dnp3/target/release/deps/libmemchr-0b36fee4e09e12a3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/build/serde_json-c1f9c3dcffe62a42/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#subtle@2.6.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"subtle","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsubtle-2c5af15982bd0d6a.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsubtle-2c5af15982bd0d6a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#log@0.4.29","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/log-0.4.29/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"log","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/log-0.4.29/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblog-fb385694826f2088.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblog-fb385694826f2088.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#find-msvc-tools@0.1.9","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/find-msvc-tools-0.1.9/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"find_msvc_tools","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/find-msvc-tools-0.1.9/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libfind_msvc_tools-c2e0b1f19d8c6254.rlib","/build/dnp3/target/release/deps/libfind_msvc_tools-c2e0b1f19d8c6254.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#utf8parse@0.2.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/utf8parse-0.2.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"utf8parse","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/utf8parse-0.2.2/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default"],"filenames":["/build/dnp3/target/release/deps/libutf8parse-73a0c37e0c4b036d.rlib","/build/dnp3/target/release/deps/libutf8parse-73a0c37e0c4b036d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#shlex@1.3.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/shlex-1.3.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"shlex","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/shlex-1.3.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libshlex-b179ddb968436a02.rlib","/build/dnp3/target/release/deps/libshlex-b179ddb968436a02.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#zeroize@1.8.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zeroize-1.8.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"zeroize","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zeroize-1.8.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libzeroize-aa9c3200ffc9bb97.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libzeroize-aa9c3200ffc9bb97.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/once_cell-1.21.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"once_cell","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/once_cell-1.21.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default","race","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libonce_cell-6e50d1ba9ef3d8ad.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libonce_cell-6e50d1ba9ef3d8ad.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#anstyle-query@1.1.5","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-query-1.1.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"anstyle_query","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-query-1.1.5/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libanstyle_query-9b42a193c1050938.rlib","/build/dnp3/target/release/deps/libanstyle_query-9b42a193c1050938.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#is_terminal_polyfill@1.70.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/is_terminal_polyfill-1.70.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"is_terminal_polyfill","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/is_terminal_polyfill-1.70.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default"],"filenames":["/build/dnp3/target/release/deps/libis_terminal_polyfill-ea6316c19614d7f3.rlib","/build/dnp3/target/release/deps/libis_terminal_polyfill-ea6316c19614d7f3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#object@0.37.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/object-0.37.3/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/object-0.37.3/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["archive","coff","elf","macho","pe","read_core","unaligned","xcoff"],"filenames":["/build/dnp3/target/release/build/object-f29e28d21cf1c13a/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#colorchoice@1.0.5","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/colorchoice-1.0.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"colorchoice","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/colorchoice-1.0.5/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libcolorchoice-c697909ffec6e90b.rlib","/build/dnp3/target/release/deps/libcolorchoice-c697909ffec6e90b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#anstyle@1.0.14","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-1.0.14/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"anstyle","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-1.0.14/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libanstyle-ecb2a8503060039e.rlib","/build/dnp3/target/release/deps/libanstyle-ecb2a8503060039e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.17","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pin-project-lite-0.2.17/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pin_project_lite","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pin-project-lite-0.2.17/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpin_project_lite-810466feb861c31e.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpin_project_lite-810466feb861c31e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#platforms@2.0.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/platforms-2.0.0/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/platforms-2.0.0/build.rs","edition":"2018","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/build/platforms-277c5ff807870cef/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#regex-syntax@0.8.10","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-syntax-0.8.10/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"regex_syntax","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-syntax-0.8.10/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std","unicode","unicode-age","unicode-bool","unicode-case","unicode-gencat","unicode-perl","unicode-script","unicode-segment"],"filenames":["/build/dnp3/target/release/deps/libregex_syntax-792826352cca3ffb.rlib","/build/dnp3/target/release/deps/libregex_syntax-792826352cca3ffb.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","derive","serde_derive","std"],"filenames":["/build/dnp3/target/release/build/serde-214c13a0b92d23df/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.106","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/proc-macro2-1.0.106/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"proc_macro2","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/proc-macro2-1.0.106/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","proc-macro"],"filenames":["/build/dnp3/target/release/deps/libproc_macro2-09a9c2d5277a398f.rlib","/build/dnp3/target/release/deps/libproc_macro2-09a9c2d5277a398f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#generic-array@0.14.7","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/build.rs","edition":"2015","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["more_lengths"],"filenames":["/build/dnp3/target/release/build/generic-array-64cb29654dbed717/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#anstyle-parse@1.0.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-parse-1.0.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"anstyle_parse","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstyle-parse-1.0.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","utf8"],"filenames":["/build/dnp3/target/release/deps/libanstyle_parse-593540c538afddf9.rlib","/build/dnp3/target/release/deps/libanstyle_parse-593540c538afddf9.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#aho-corasick@1.1.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"aho_corasick","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aho-corasick-1.1.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["perf-literal","std"],"filenames":["/build/dnp3/target/release/deps/libaho_corasick-77defa4be01757f5.rlib","/build/dnp3/target/release/deps/libaho_corasick-77defa4be01757f5.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#adler2@2.0.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/adler2-2.0.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"adler2","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/adler2-2.0.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libadler2-0a85de5109f6fe71.rlib","/build/dnp3/target/release/deps/libadler2-0a85de5109f6fe71.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#heck@0.5.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/heck-0.5.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"heck","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/heck-0.5.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libheck-93c7fa174c74aabf.rlib","/build/dnp3/target/release/deps/libheck-93c7fa174c74aabf.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#gimli@0.32.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/gimli-0.32.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"gimli","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/gimli-0.32.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["read","read-core"],"filenames":["/build/dnp3/target/release/deps/libgimli-4a7f42e256b7913e.rlib","/build/dnp3/target/release/deps/libgimli-4a7f42e256b7913e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#once_cell@1.21.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/once_cell-1.21.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"once_cell","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/once_cell-1.21.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default","race","std"],"filenames":["/build/dnp3/target/release/deps/libonce_cell-020eb50cb4eb8f6c.rlib","/build/dnp3/target/release/deps/libonce_cell-020eb50cb4eb8f6c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#strsim@0.11.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/strsim-0.11.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"strsim","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/strsim-0.11.1/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libstrsim-8f54055135456a8d.rlib","/build/dnp3/target/release/deps/libstrsim-8f54055135456a8d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#clap_lex@1.1.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_lex-1.1.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"clap_lex","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_lex-1.1.0/src/lib.rs","edition":"2024","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libclap_lex-e38f1954cd59c843.rlib","/build/dnp3/target/release/deps/libclap_lex-e38f1954cd59c843.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cpufeatures@0.2.17","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cpufeatures-0.2.17/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cpufeatures","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cpufeatures-0.2.17/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcpufeatures-929461b872a5ccc6.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcpufeatures-929461b872a5ccc6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#memchr@2.8.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/memchr-2.8.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"memchr","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/memchr-2.8.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmemchr-7aca204303c41f8a.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmemchr-7aca204303c41f8a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rustc-demangle@0.1.27","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustc-demangle-0.1.27/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rustc_demangle","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustc-demangle-0.1.27/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/librustc_demangle-6a59aac61a06e0ef.rlib","/build/dnp3/target/release/deps/librustc_demangle-6a59aac61a06e0ef.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.17","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pin-project-lite-0.2.17/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pin_project_lite","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pin-project-lite-0.2.17/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libpin_project_lite-3a4baeff80c5302d.rlib","/build/dnp3/target/release/deps/libpin_project_lite-3a4baeff80c5302d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#base64ct@1.8.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/base64ct-1.8.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"base64ct","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/base64ct-1.8.3/src/lib.rs","edition":"2024","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbase64ct-c349615a7831b303.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbase64ct-c349615a7831b303.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg-if-1.0.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cfg_if","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg-if-1.0.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libcfg_if-28021643dc2490eb.rlib","/build/dnp3/target/release/deps/libcfg_if-28021643dc2490eb.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/itoa-1.0.18/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"itoa","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/itoa-1.0.18/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libitoa-7a4cbf85b66f6f98.rlib","/build/dnp3/target/release/deps/libitoa-7a4cbf85b66f6f98.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#const-oid@0.9.6","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/const-oid-0.9.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"const_oid","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/const-oid-0.9.6/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libconst_oid-bb9af13a578d33cf.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libconst_oid-bb9af13a578d33cf.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-core-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-core-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_core-a7082f6d877ddcd4.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_core-a7082f6d877ddcd4.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#untrusted@0.9.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/untrusted-0.9.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"untrusted","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/untrusted-0.9.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libuntrusted-65cbb5a2291a69c6.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libuntrusted-65cbb5a2291a69c6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#lazy_static@1.5.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lazy_static-1.5.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"lazy_static","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lazy_static-1.5.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/liblazy_static-3059ee5ae6a8cc41.rlib","/build/dnp3/target/release/deps/liblazy_static-3059ee5ae6a8cc41.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#semver@1.0.28","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/semver-1.0.28/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"semver","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/semver-1.0.28/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libsemver-3d112b812fea401c.rlib","/build/dnp3/target/release/deps/libsemver-3d112b812fea401c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cfg_aliases@0.2.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg_aliases-0.2.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cfg_aliases","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cfg_aliases-0.2.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libcfg_aliases-eb1b10a1b3309217.rlib","/build/dnp3/target/release/deps/libcfg_aliases-eb1b10a1b3309217.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#dunce@1.0.5","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/dunce-1.0.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"dunce","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/dunce-1.0.5/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libdunce-47dea079ba20012f.rlib","/build/dnp3/target/release/deps/libdunce-47dea079ba20012f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#autocfg@1.5.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/autocfg-1.5.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"autocfg","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/autocfg-1.5.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libautocfg-da071fec8bb21226.rlib","/build/dnp3/target/release/deps/libautocfg-da071fec8bb21226.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-sink@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-sink-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_sink","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-sink-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_sink-73d9619ecc0a0389.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_sink-73d9619ecc0a0389.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rustls-pki-types@1.14.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-pki-types-1.14.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rustls_pki_types","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-pki-types-1.14.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librustls_pki_types-31db3f15d1e87c36.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librustls_pki_types-31db3f15d1e87c36.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-core@0.1.36","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-core-0.1.36/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-core-0.1.36/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","once_cell","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_core-82ef0b2b5d9ce9e7.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_core-82ef0b2b5d9ce9e7.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-task@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-task-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_task","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-task-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_task-f6543aaa23fe99d3.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_task-f6543aaa23fe99d3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-io@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-io-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_io","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-io-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_io-374b7042d2c9975a.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_io-374b7042d2c9975a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#bitflags@2.11.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bitflags-2.11.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"bitflags","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bitflags-2.11.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbitflags-3ab978bdc6462f74.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbitflags-3ab978bdc6462f74.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#bitflags@1.3.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bitflags-1.3.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"bitflags","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bitflags-1.3.2/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbitflags-f000714ba261c10e.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbitflags-f000714ba261c10e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#slab@0.4.12","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/slab-0.4.12/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"slab","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/slab-0.4.12/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libslab-a3aec08dfc33854e.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libslab-a3aec08dfc33854e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#quote@1.0.45","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.45/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"quote","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/quote-1.0.45/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","proc-macro"],"filenames":["/build/dnp3/target/release/deps/libquote-6462f4c5c001e9d8.rlib","/build/dnp3/target/release/deps/libquote-6462f4c5c001e9d8.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#typenum@1.19.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/typenum-1.19.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"typenum","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/typenum-1.19.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtypenum-85426667bb29b4de.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtypenum-85426667bb29b4de.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#libc@0.2.185","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"libc","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","extra_traits","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblibc-7aa287e1b53fba70.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblibc-7aa287e1b53fba70.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#anstream@1.0.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstream-1.0.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"anstream","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/anstream-1.0.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["auto","default","wincon"],"filenames":["/build/dnp3/target/release/deps/libanstream-f3a8feeed99a23cb.rlib","/build/dnp3/target/release/deps/libanstream-f3a8feeed99a23cb.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["result","std"],"filenames":["/build/dnp3/target/release/deps/libserde_core-5920ff8c9013a0f6.rlib","/build/dnp3/target/release/deps/libserde_core-5920ff8c9013a0f6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#addr2line@0.25.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/addr2line-0.25.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"addr2line","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/addr2line-0.25.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libaddr2line-f290ebcd30e046fd.rlib","/build/dnp3/target/release/deps/libaddr2line-f290ebcd30e046fd.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#regex-automata@0.4.14","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-automata-0.4.14/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"regex_automata","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-automata-0.4.14/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","dfa-onepass","hybrid","meta","nfa-backtrack","nfa-pikevm","nfa-thompson","perf-inline","perf-literal","perf-literal-multisubstring","perf-literal-substring","std","syntax","unicode","unicode-age","unicode-bool","unicode-case","unicode-gencat","unicode-perl","unicode-script","unicode-segment","unicode-word-boundary"],"filenames":["/build/dnp3/target/release/deps/libregex_automata-078445f3e0f0837f.rlib","/build/dnp3/target/release/deps/libregex_automata-078445f3e0f0837f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"zmij","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libzmij-534094fc2277839f.rlib","/build/dnp3/target/release/deps/libzmij-534094fc2277839f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-core@0.1.36","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-core-0.1.36/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-core-0.1.36/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["once_cell","std"],"filenames":["/build/dnp3/target/release/deps/libtracing_core-a935839dcef5e16d.rlib","/build/dnp3/target/release/deps/libtracing_core-a935839dcef5e16d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#object@0.37.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/object-0.37.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"object","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/object-0.37.3/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["archive","coff","elf","macho","pe","read_core","unaligned","xcoff"],"filenames":["/build/dnp3/target/release/deps/libobject-15b73b119d7e6c19.rlib","/build/dnp3/target/release/deps/libobject-15b73b119d7e6c19.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#miniz_oxide@0.8.9","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/miniz_oxide-0.8.9/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"miniz_oxide","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/miniz_oxide-0.8.9/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libminiz_oxide-d6022a4640c802c8.rlib","/build/dnp3/target/release/deps/libminiz_oxide-d6022a4640c802c8.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#platforms@2.0.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/platforms-2.0.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"platforms","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/platforms-2.0.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libplatforms-e80f3a3d3e398e25.rlib","/build/dnp3/target/release/deps/libplatforms-e80f3a3d3e398e25.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pem-rfc7468@0.7.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pem-rfc7468-0.7.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pem_rfc7468","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pem-rfc7468-0.7.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpem_rfc7468-1fde0d11529dd55a.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpem_rfc7468-1fde0d11529dd55a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-channel@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-channel-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_channel","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-channel-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","futures-sink","sink","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_channel-6701040026dbdfe0.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_channel-6701040026dbdfe0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#nix@0.29.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.29.0/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.29.0/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","term"],"filenames":["/build/dnp3/target/release/build/nix-0c607e222c597047/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#num-traits@0.2.19","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/build/num-traits-d9b6f1fd82a543cd/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_core@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_core-1.0.228/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["result","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde_core-07165d9ae25357c3.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde_core-07165d9ae25357c3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/build/serde-51f8cabc1e92e4be/build-script-build"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#scopeguard@1.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scopeguard-1.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"scopeguard","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scopeguard-1.2.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","use_std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscopeguard-709824b4872089ef.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscopeguard-709824b4872089ef.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#bytes@1.11.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.11.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"bytes","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.11.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbytes-1bafb44421458806.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbytes-1bafb44421458806.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#base64@0.22.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/base64-0.22.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"base64","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/base64-0.22.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbase64-b8811b76be2877b0.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libbase64-b8811b76be2877b0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rand_core@0.6.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rand_core-0.6.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rand_core","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rand_core-0.6.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librand_core-4d09d55f4fd7128d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librand_core-4d09d55f4fd7128d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#iana-time-zone@0.1.65","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iana-time-zone-0.1.65/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"iana_time_zone","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/iana-time-zone-0.1.65/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["fallback"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libiana_time_zone-96b6b12d923f1a62.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libiana_time_zone-96b6b12d923f1a62.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/itoa-1.0.18/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"itoa","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/itoa-1.0.18/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libitoa-dde2abcaca5abe8c.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libitoa-dde2abcaca5abe8c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rx509@0.2.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rx509-0.2.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rx509","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rx509-0.2.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librx509-1f28384b53d23d1d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librx509-1f28384b53d23d1d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#lazy_static@1.5.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lazy_static-1.5.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"lazy_static","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lazy_static-1.5.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblazy_static-6c465f40d154fe00.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/liblazy_static-6c465f40d154fe00.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-log@0.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-log-0.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing_log","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-log-0.2.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["log-tracer","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_log-e72fd1edaf8ad851.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_log-e72fd1edaf8ad851.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#thread_local@1.1.9","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thread_local-1.1.9/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"thread_local","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thread_local-1.1.9/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libthread_local-91eedfb3bbaa910e.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libthread_local-91eedfb3bbaa910e.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#scursor@0.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scursor-0.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"scursor","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scursor-0.2.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscursor-5b5b156e044eee67.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscursor-5b5b156e044eee67.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#nu-ansi-term@0.50.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nu-ansi-term-0.50.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"nu_ansi_term","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nu-ansi-term-0.50.3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnu_ansi_term-f18bc27446c795e0.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnu_ansi_term-f18bc27446c795e0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#smallvec@1.15.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/smallvec-1.15.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"smallvec","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/smallvec-1.15.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsmallvec-7352a0982df94947.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsmallvec-7352a0982df94947.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#xxhash-rust@0.8.15","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/xxhash-rust-0.8.15/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"xxhash_rust","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/xxhash-rust-0.8.15/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["xxh64"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libxxhash_rust-f13c01620dfcf5a0.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libxxhash_rust-f13c01620dfcf5a0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sfio-promise@0.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-promise-0.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sfio_promise","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-promise-0.2.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsfio_promise-3bbf3f288fa4b841.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsfio_promise-3bbf3f288fa4b841.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#syn@2.0.117","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/syn-2.0.117/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"syn","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/syn-2.0.117/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["clone-impls","default","derive","extra-traits","full","parsing","printing","proc-macro","visit-mut"],"filenames":["/build/dnp3/target/release/deps/libsyn-5fb96b0047a8d00b.rlib","/build/dnp3/target/release/deps/libsyn-5fb96b0047a8d00b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#generic-array@0.14.7","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"generic_array","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/generic-array-0.14.7/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["more_lengths"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libgeneric_array-d865f073403721f1.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libgeneric_array-d865f073403721f1.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#clap_builder@4.6.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_builder-4.6.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"clap_builder","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_builder-4.6.0/src/lib.rs","edition":"2024","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["color","error-context","help","std","suggestions","usage"],"filenames":["/build/dnp3/target/release/deps/libclap_builder-43442bdfba6d37d3.rlib","/build/dnp3/target/release/deps/libclap_builder-43442bdfba6d37d3.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde_json","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libserde_json-d2e34e61967fb2ba.rlib","/build/dnp3/target/release/deps/libserde_json-d2e34e61967fb2ba.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#regex@1.12.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-1.12.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"regex","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/regex-1.12.3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","perf","perf-backtrack","perf-cache","perf-dfa","perf-inline","perf-literal","perf-onepass","std","unicode","unicode-age","unicode-bool","unicode-case","unicode-gencat","unicode-perl","unicode-script","unicode-segment"],"filenames":["/build/dnp3/target/release/deps/libregex-8ffde440f03af825.rlib","/build/dnp3/target/release/deps/libregex-8ffde440f03af825.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#der@0.7.10","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/der-0.7.10/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"der","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/der-0.7.10/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","oid","pem","std","zeroize"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libder-de10fa2da9486bf5.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libder-de10fa2da9486bf5.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#mio@1.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/mio-1.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"mio","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/mio-1.2.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","log","net","os-ext","os-poll"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmio-7f36e802fc95a965.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmio-7f36e802fc95a965.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#socket2@0.6.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/socket2-0.6.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"socket2","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/socket2-0.6.3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["all"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsocket2-158d33b8c9af4d1b.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsocket2-158d33b8c9af4d1b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#nix@0.26.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.26.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"nix","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.26.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["fs","ioctl","poll","process","signal","term"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnix-7c02514e7ca9d6a6.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnix-7c02514e7ca9d6a6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#zmij@1.0.21","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"zmij","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/zmij-1.0.21/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libzmij-84b4b84d7e563c3a.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libzmij-84b4b84d7e563c3a.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pem@3.0.6","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pem-3.0.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pem","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pem-3.0.6/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpem-c9261c5440120518.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpem-c9261c5440120518.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sharded-slab@0.1.7","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sharded-slab-0.1.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sharded_slab","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sharded-slab-0.1.7/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsharded_slab-ab41f9ced168e4cd.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsharded_slab-ab41f9ced168e4cd.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#num_cpus@1.17.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num_cpus-1.17.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"num_cpus","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num_cpus-1.17.0/src/lib.rs","edition":"2015","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnum_cpus-c2d81ff4a539fff9.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnum_cpus-c2d81ff4a539fff9.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#crypto-common@0.1.7","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-common-0.1.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"crypto_common","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crypto-common-0.1.7/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcrypto_common-9679b68da4f0e548.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcrypto_common-9679b68da4f0e548.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#thiserror-impl@2.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-impl-2.0.18/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"thiserror_impl","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-impl-2.0.18/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libthiserror_impl-6015b27eb24967d3.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#block-padding@0.3.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-padding-0.3.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"block_padding","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-padding-0.3.3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libblock_padding-2fc88dc0097b833f.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libblock_padding-2fc88dc0097b833f.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#block-buffer@0.10.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"block_buffer","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/block-buffer-0.10.4/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libblock_buffer-03f8f27e5f119e25.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libblock_buffer-03f8f27e5f119e25.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-attributes@0.1.31","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-attributes-0.1.31/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"tracing_attributes","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-attributes-0.1.31/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libtracing_attributes-e07a510e942fb0ba.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_derive@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_derive-1.0.228/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"serde_derive","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_derive-1.0.228/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default"],"filenames":["/build/dnp3/target/release/deps/libserde_derive-efbe97b1aac3fb04.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#clap_derive@4.6.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_derive-4.6.1/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"clap_derive","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap_derive-4.6.1/src/lib.rs","edition":"2024","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default"],"filenames":["/build/dnp3/target/release/deps/libclap_derive-27ecf755bbbf1c26.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-macro@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-macro-0.3.32/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"futures_macro","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-macro-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libfutures_macro-571b160132d0a57d.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tokio-macros@2.7.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-macros-2.7.0/Cargo.toml","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"tokio_macros","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-macros-2.7.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libtokio_macros-6b3bd1dac3dd39ab.so"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#spki@0.7.3","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spki-0.7.3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"spki","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/spki-0.7.3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","pem","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libspki-573b800b49943744.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libspki-573b800b49943744.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#nix@0.29.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.29.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"nix","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/nix-0.29.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","term"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnix-e06722d453f9107d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnix-e06722d453f9107d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#num-traits@0.2.19","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"num_traits","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/num-traits-0.2.19/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnum_traits-8c1f986c2103613d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libnum_traits-8c1f986c2103613d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde-9ff2552f4a980ede.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde-9ff2552f4a980ede.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.149","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde_json","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde_json-1.0.149/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde_json-9f6410fc50d8ea84.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserde_json-9f6410fc50d8ea84.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#inout@0.1.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/inout-0.1.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"inout","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/inout-0.1.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["block-padding"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libinout-404802b1e1036e8d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libinout-404802b1e1036e8d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#digest@0.10.7","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"digest","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/digest-0.10.7/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["block-buffer","core-api","default","mac","subtle"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libdigest-5922d1be4fa8657d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libdigest-5922d1be4fa8657d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#clap@4.6.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap-4.6.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"clap","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/clap-4.6.1/src/lib.rs","edition":"2024","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["color","default","derive","error-context","help","std","suggestions","usage"],"filenames":["/build/dnp3/target/release/deps/libclap-d2c57e3c24a11cf4.rlib","/build/dnp3/target/release/deps/libclap-d2c57e3c24a11cf4.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serde@1.0.228","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serde","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","derive","serde_derive","std"],"filenames":["/build/dnp3/target/release/deps/libserde-446a2d07d006ea70.rlib","/build/dnp3/target/release/deps/libserde-446a2d07d006ea70.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-0.1.44/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-0.1.44/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["attributes","default","std","tracing-attributes"],"filenames":["/build/dnp3/target/release/deps/libtracing-ea3fdfbe4af6faea.rlib","/build/dnp3/target/release/deps/libtracing-ea3fdfbe4af6faea.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"thiserror","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libthiserror-05cf950e48f3f308.rlib","/build/dnp3/target/release/deps/libthiserror-05cf950e48f3f308.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#thiserror@2.0.18","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"thiserror","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/thiserror-2.0.18/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libthiserror-9e714939f5b7af64.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libthiserror-9e714939f5b7af64.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-util@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-util-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_util","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-util-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","async-await","async-await-macro","channel","futures-channel","futures-io","futures-macro","futures-sink","io","memchr","sink","slab","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_util-4199551f783914da.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_util-4199551f783914da.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tokio@1.52.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.52.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tokio","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.52.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["bytes","default","io-std","io-util","libc","macros","mio","net","rt","rt-multi-thread","socket2","sync","time","tokio-macros"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio-52c4c55fe9d3605b.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio-52c4c55fe9d3605b.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#chrono@0.4.44","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"chrono","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/chrono-0.4.44/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","clock","default","iana-time-zone","js-sys","now","oldtime","std","wasm-bindgen","wasmbind","winapi","windows-link"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libchrono-599bb9ad7de9cc61.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libchrono-599bb9ad7de9cc61.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-serde@0.2.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-serde-0.2.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing_serde","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-serde-0.2.0/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_serde-4bb271aa612b1563.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_serde-4bb271aa612b1563.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.44","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-0.1.44/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-0.1.44/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["attributes","default","std","tracing-attributes"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing-4ca4880ee0c721ca.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing-4ca4880ee0c721ca.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cipher@0.4.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cipher-0.4.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cipher","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cipher-0.4.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["block-padding"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcipher-6817574d857e43e0.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcipher-6817574d857e43e0.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#hmac@0.12.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hmac-0.12.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"hmac","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/hmac-0.12.1/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libhmac-a2076952c48b3f77.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libhmac-a2076952c48b3f77.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sha2@0.10.9","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sha2-0.10.9/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sha2","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sha2-0.10.9/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsha2-87ac78cfadeda05d.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsha2-87ac78cfadeda05d.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#unescaper@0.1.8","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/unescaper-0.1.8/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"unescaper","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/unescaper-0.1.8/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libunescaper-6e0589f217e3009c.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libunescaper-6e0589f217e3009c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures-executor@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-executor-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures_executor","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-executor-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_executor-e7c81904d84f37f6.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures_executor-e7c81904d84f37f6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tracing-subscriber@0.3.23","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-subscriber-0.3.23/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tracing_subscriber","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tracing-subscriber-0.3.23/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","ansi","chrono","default","fmt","json","nu-ansi-term","registry","serde","serde_json","sharded-slab","smallvec","std","thread_local","tracing-log","tracing-serde"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_subscriber-cdf73b24c9181685.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtracing_subscriber-cdf73b24c9181685.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#salsa20@0.10.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/salsa20-0.10.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"salsa20","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/salsa20-0.10.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsalsa20-b608be23fb6d77ef.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsalsa20-b608be23fb6d77ef.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pbkdf2@0.12.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pbkdf2-0.12.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pbkdf2","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pbkdf2-0.12.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","hmac"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpbkdf2-17a4c0874b25ecdf.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpbkdf2-17a4c0874b25ecdf.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cbc@0.1.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cbc-0.1.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cbc","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cbc-0.1.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["block-padding","default"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcbc-6132f6e9c72a2714.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libcbc-6132f6e9c72a2714.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#aes@0.8.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aes-0.8.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"aes","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/aes-0.8.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libaes-d63f74f7f5c343ff.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libaes-d63f74f7f5c343ff.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#serialport@4.9.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serialport-4.9.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"serialport","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serialport-4.9.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserialport-fe71e642ec3210db.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libserialport-fe71e642ec3210db.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#futures@0.3.32","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-0.3.32/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"futures","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-0.3.32/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","async-await","default","executor","futures-executor","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures-5a3a901221140d3c.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libfutures-5a3a901221140d3c.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#scrypt@0.11.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scrypt-0.11.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"scrypt","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scrypt-0.11.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscrypt-824ed7f357740171.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libscrypt-824ed7f357740171.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#mio-serial@5.0.6","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/mio-serial-5.0.6/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"mio_serial","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/mio-serial-5.0.6/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmio_serial-264dc879ebc68924.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libmio_serial-264dc879ebc68924.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pkcs5@0.7.1","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkcs5-0.7.1/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pkcs5","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkcs5-0.7.1/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","pbes2"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpkcs5-01694de4ef65ac91.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpkcs5-01694de4ef65ac91.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tokio-serial@5.4.5","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-serial-5.4.5/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tokio_serial","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-serial-5.4.5/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio_serial-dc236905d7ed18d6.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio_serial-dc236905d7ed18d6.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#pkcs8@0.10.2","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkcs8-0.10.2/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"pkcs8","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/pkcs8-0.10.2/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","encryption","pem","pkcs5","rand_core","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpkcs8-456c60df3aa91c68.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libpkcs8-456c60df3aa91c68.rmeta"],"executable":null,"fresh":true} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rustls@0.23.45","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.45/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.45/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["log","logging","ring","std","tls12"],"filenames":["/build/dnp3/target/release/build/rustls-7e701616b8d60b1f/build-script-build"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#getrandom@0.2.17","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/getrandom-0.2.17/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"getrandom","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/getrandom-0.2.17/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libgetrandom-915c3d9c7a90fa1b.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libgetrandom-915c3d9c7a90fa1b.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#libc@0.2.185","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/build/libc-12e63f2756d9fa30/build-script-build"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#cc@1.2.60","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cc-1.2.60/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"cc","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cc-1.2.60/src/lib.rs","edition":"2018","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libcc-1bf60ba252f4dbaf.rlib","/build/dnp3/target/release/deps/libcc-1bf60ba252f4dbaf.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#libc@0.2.185","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"libc","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/libc-0.2.185/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/liblibc-6bd54fcf62805039.rlib","/build/dnp3/target/release/deps/liblibc-6bd54fcf62805039.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#ring@0.17.14","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ring-0.17.14/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ring-0.17.14/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default","dev_urandom_fallback"],"filenames":["/build/dnp3/target/release/build/ring-a2a0298fe3443fd8/build-script-build"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#backtrace@0.3.76","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/backtrace-0.3.76/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"backtrace","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/backtrace-0.3.76/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["default","std"],"filenames":["/build/dnp3/target/release/deps/libbacktrace-17addfd0fca5f274.rlib","/build/dnp3/target/release/deps/libbacktrace-17addfd0fca5f274.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sfio-tracing-ffi@0.9.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-tracing-ffi-0.9.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sfio_tracing_ffi","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-tracing-ffi-0.9.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libsfio_tracing_ffi-97dda26a838d9f5f.rlib","/build/dnp3/target/release/deps/libsfio_tracing_ffi-97dda26a838d9f5f.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sfio-tokio-ffi@0.9.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-tokio-ffi-0.9.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sfio_tokio_ffi","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-tokio-ffi-0.9.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libsfio_tokio_ffi-e05017e4d4f587f0.rlib","/build/dnp3/target/release/deps/libsfio_tokio_ffi-e05017e4d4f587f0.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#oo-bindgen@0.8.8","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/oo-bindgen-0.8.8/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"oo_bindgen","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/oo-bindgen-0.8.8/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/liboo_bindgen-9413fc7862d1f578.rlib","/build/dnp3/target/release/deps/liboo_bindgen-9413fc7862d1f578.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"path+file:///build/dnp3/ffi/dnp3-schema#1.7.0","manifest_path":"/build/dnp3/ffi/dnp3-schema/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"dnp3_schema","src_path":"/build/dnp3/ffi/dnp3-schema/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":[],"filenames":["/build/dnp3/target/release/deps/libdnp3_schema-7979dfe4b6e7b7c3.rlib","/build/dnp3/target/release/deps/libdnp3_schema-7979dfe4b6e7b7c3.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"path+file:///build/dnp3/ffi/dnp3-ffi#1.7.0","manifest_path":"/build/dnp3/ffi/dnp3-ffi/Cargo.toml","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-build","src_path":"/build/dnp3/ffi/dnp3-ffi/build.rs","edition":"2021","doc":false,"doctest":false,"test":false},"profile":{"opt_level":"0","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["enable-tls","serial","tls"],"filenames":["/build/dnp3/target/release/build/dnp3-ffi-69879bfa9a004339/build-script-build"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#ring@0.17.14","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ring-0.17.14/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"ring","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ring-0.17.14/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","default","dev_urandom_fallback"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libring-5e48c2ae02954d63.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libring-5e48c2ae02954d63.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rustls-webpki@0.103.15","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-webpki-0.103.15/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"webpki","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-webpki-0.103.15/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["alloc","ring","std"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libwebpki-ebcfd2703b2d9a9b.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libwebpki-ebcfd2703b2d9a9b.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#tokio-rustls@0.26.4","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-rustls-0.26.4/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"tokio_rustls","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-rustls-0.26.4/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["tls12"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio_rustls-9ddd316ed3b590b3.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libtokio_rustls-9ddd316ed3b590b3.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#sfio-rustls-config@0.4.0","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-rustls-config-0.4.0/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"sfio_rustls_config","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfio-rustls-config-0.4.0/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["crypto-ring","default"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsfio_rustls_config-0a71a689305227fa.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libsfio_rustls_config-0a71a689305227fa.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"registry+https://github.com/rust-lang/crates.io-index#rustls@0.23.45","manifest_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.45/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"rustls","src_path":"/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.45/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["log","logging","ring","std","tls12"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librustls-7b9aec4c8c059ab8.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/librustls-7b9aec4c8c059ab8.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"path+file:///build/dnp3/dnp3#1.7.0","manifest_path":"/build/dnp3/dnp3/Cargo.toml","target":{"kind":["lib"],"crate_types":["lib"],"name":"dnp3","src_path":"/build/dnp3/dnp3/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["enable-tls","ffi","serial","sfio-rustls-config","tls","tokio-rustls","tokio-serial"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libdnp3-1418254c0dd71413.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/deps/libdnp3-1418254c0dd71413.rmeta"],"executable":null,"fresh":false} +{"reason":"compiler-artifact","package_id":"path+file:///build/dnp3/ffi/dnp3-ffi#1.7.0","manifest_path":"/build/dnp3/ffi/dnp3-ffi/Cargo.toml","target":{"kind":["rlib","cdylib"],"crate_types":["rlib","cdylib"],"name":"dnp3_ffi","src_path":"/build/dnp3/ffi/dnp3-ffi/src/lib.rs","edition":"2021","doc":true,"doctest":true,"test":true},"profile":{"opt_level":"3","debuginfo":0,"debug_assertions":false,"overflow_checks":false,"test":false},"features":["enable-tls","serial","tls"],"filenames":["/build/dnp3/target/x86_64-unknown-linux-gnu/release/libdnp3_ffi.rlib","/build/dnp3/target/x86_64-unknown-linux-gnu/release/libdnp3_ffi.so"],"executable":null,"fresh":false} +{"reason":"build-finished","success":true} diff --git a/allow-list/tests/fixtures/dnp3/targets/ring/runtime-tree.txt b/allow-list/tests/fixtures/dnp3/targets/ring/runtime-tree.txt new file mode 100644 index 0000000..42e6f59 --- /dev/null +++ b/allow-list/tests/fixtures/dnp3/targets/ring/runtime-tree.txt @@ -0,0 +1,162 @@ +0dnp3-ffi v1.7.0 (/build/dnp3/ffi/dnp3-ffi)|enable-tls,serial,tls +1dnp3 v1.7.0 (/build/dnp3/dnp3)|enable-tls,ffi,serial,sfio-rustls-config,tls,tokio-rustls,tokio-serial +2chrono v0.4.44|alloc,clock,default,iana-time-zone,js-sys,now,oldtime,std,wasm-bindgen,wasmbind,winapi,windows-link +3iana-time-zone v0.1.65|fallback +3num-traits v0.2.19| +2scursor v0.2.0| +2sfio-rustls-config v0.4.0|crypto-ring,default +3pem v3.0.6|default,std +4base64 v0.22.1|alloc,std +3pkcs8 v0.10.2|alloc,encryption,pem,pkcs5,rand_core,std +4der v0.7.10|alloc,oid,pem,std,zeroize +5const-oid v0.9.6| +5pem-rfc7468 v0.7.0|alloc +6base64ct v1.8.3|alloc +5zeroize v1.8.2|alloc,default +4pkcs5 v0.7.1|alloc,pbes2 +5aes v0.8.4| +6cfg-if v1.0.4| +6cipher v0.4.4|block-padding +7crypto-common v0.1.7| +8generic-array v0.14.7|more_lengths +9typenum v1.19.0| +8typenum v1.19.0| +7inout v0.1.4|block-padding +8block-padding v0.3.3| +9generic-array v0.14.7|more_lengths (*) +8generic-array v0.14.7|more_lengths (*) +6cpufeatures v0.2.17| +5cbc v0.1.2|block-padding,default +6cipher v0.4.4|block-padding (*) +5der v0.7.10|alloc,oid,pem,std,zeroize (*) +5pbkdf2 v0.12.2|default,hmac +6digest v0.10.7|block-buffer,core-api,default,mac,subtle +7block-buffer v0.10.4| +8generic-array v0.14.7|more_lengths (*) +7crypto-common v0.1.7| (*) +7subtle v2.6.1| +6hmac v0.12.1| +7digest v0.10.7|block-buffer,core-api,default,mac,subtle (*) +5scrypt v0.11.0| +6pbkdf2 v0.12.2|default,hmac (*) +6salsa20 v0.10.2| +7cipher v0.4.4|block-padding (*) +6sha2 v0.10.9| +7cfg-if v1.0.4| +7cpufeatures v0.2.17| +7digest v0.10.7|block-buffer,core-api,default,mac,subtle (*) +5sha2 v0.10.9| (*) +5spki v0.7.3|alloc,pem,std +6der v0.7.10|alloc,oid,pem,std,zeroize (*) +4rand_core v0.6.4| +4spki v0.7.3|alloc,pem,std (*) +3rustls v0.23.45|log,logging,ring,std,tls12 +4log v0.4.29|std +4once_cell v1.21.4|alloc,default,race,std +4ring v0.17.14|alloc,default,dev_urandom_fallback +5cfg-if v1.0.4| +5getrandom v0.2.17| +6cfg-if v1.0.4| +6libc v0.2.185|default,extra_traits,std +5untrusted v0.9.0| +4rustls-pki-types v1.14.0|alloc,default,std +5zeroize v1.8.2|alloc,default +4rustls-webpki v0.103.15|alloc,ring,std +5ring v0.17.14|alloc,default,dev_urandom_fallback (*) +5rustls-pki-types v1.14.0|alloc,default,std (*) +5untrusted v0.9.0| +4subtle v2.6.1| +4zeroize v1.8.2|alloc,default +3rustls-pki-types v1.14.0|alloc,default,std (*) +3rustls-webpki v0.103.15|alloc,ring,std (*) +3rx509 v0.2.1| +2tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros +3bytes v1.11.1|default,std +3libc v0.2.185|default,extra_traits,std +3mio v1.2.0|default,log,net,os-ext,os-poll +4libc v0.2.185|default,extra_traits,std +4log v0.4.29|std +3pin-project-lite v0.2.17| +3socket2 v0.6.3|all +4libc v0.2.185|default,extra_traits,std +2tokio-rustls v0.26.4|tls12 +3rustls v0.23.45|log,logging,ring,std,tls12 (*) +3tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +2tokio-serial v5.4.5| +3cfg-if v1.0.4| +3futures v0.3.32|alloc,async-await,default,executor,futures-executor,std +4futures-channel v0.3.32|alloc,futures-sink,sink,std +5futures-core v0.3.32|alloc,std +5futures-sink v0.3.32|alloc,std +4futures-core v0.3.32|alloc,std +4futures-executor v0.3.32|std +5futures-core v0.3.32|alloc,std +5futures-task v0.3.32|alloc,std +5futures-util v0.3.32|alloc,async-await,async-await-macro,channel,futures-channel,futures-io,futures-macro,futures-sink,io,memchr,sink,slab,std +6futures-channel v0.3.32|alloc,futures-sink,sink,std (*) +6futures-core v0.3.32|alloc,std +6futures-io v0.3.32|std +6futures-sink v0.3.32|alloc,std +6futures-task v0.3.32|alloc,std +6memchr v2.8.0|alloc,default,std +6pin-project-lite v0.2.17| +6slab v0.4.12|std +4futures-io v0.3.32|std +4futures-sink v0.3.32|alloc,std +4futures-task v0.3.32|alloc,std +4futures-util v0.3.32|alloc,async-await,async-await-macro,channel,futures-channel,futures-io,futures-macro,futures-sink,io,memchr,sink,slab,std (*) +3log v0.4.29|std +3mio-serial v5.0.6| +4log v0.4.29|std +4mio v1.2.0|default,log,net,os-ext,os-poll (*) +4nix v0.29.0|default,term +5bitflags v2.11.1| +5cfg-if v1.0.4| +5libc v0.2.185|default,extra_traits,std +4serialport v4.9.0| +5bitflags v2.11.1| +5cfg-if v1.0.4| +5nix v0.26.4|fs,ioctl,poll,process,signal,term +6bitflags v1.3.2|default +6cfg-if v1.0.4| +6libc v0.2.185|default,extra_traits,std +5scopeguard v1.2.0|default,use_std +5unescaper v0.1.8| +6thiserror v2.0.18|default,std +3serialport v4.9.0| (*) +3tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +2tracing v0.1.44|attributes,default,std,tracing-attributes +3pin-project-lite v0.2.17| +3tracing-core v0.1.36|default,once_cell,std +4once_cell v1.21.4|alloc,default,race,std +2xxhash-rust v0.8.15|xxh64 +1lazy_static v1.5.0| +1num_cpus v1.17.0| +2libc v0.2.185|default,extra_traits,std +1sfio-promise v0.2.0| +1tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +1tracing v0.1.44|attributes,default,std,tracing-attributes (*) +1tracing-core v0.1.36|default,once_cell,std (*) +1tracing-subscriber v0.3.23|alloc,ansi,chrono,default,fmt,json,nu-ansi-term,registry,serde,serde_json,sharded-slab,smallvec,std,thread_local,tracing-log,tracing-serde +2chrono v0.4.44|alloc,clock,default,iana-time-zone,js-sys,now,oldtime,std,wasm-bindgen,wasmbind,winapi,windows-link (*) +2nu-ansi-term v0.50.3|default,std +2serde v1.0.228|default,std +3serde_core v1.0.228|result,std +2serde_json v1.0.149|default,std +3itoa v1.0.18| +3memchr v2.8.0|alloc,default,std +3serde_core v1.0.228|result,std +3zmij v1.0.21| +2sharded-slab v0.1.7| +3lazy_static v1.5.0| +2smallvec v1.15.1| +2thread_local v1.1.9| +3cfg-if v1.0.4| +2tracing-core v0.1.36|default,once_cell,std (*) +2tracing-log v0.2.0|log-tracer,std +3log v0.4.29|std +3once_cell v1.21.4|alloc,default,race,std +3tracing-core v0.1.36|default,once_cell,std (*) +2tracing-serde v0.2.0| +3serde v1.0.228|default,std (*) +3tracing-core v0.1.36|default,once_cell,std (*) diff --git a/allow-list/tests/fixtures/dnp3/targets/ring/tree.txt b/allow-list/tests/fixtures/dnp3/targets/ring/tree.txt new file mode 100644 index 0000000..049eb21 --- /dev/null +++ b/allow-list/tests/fixtures/dnp3/targets/ring/tree.txt @@ -0,0 +1,258 @@ +0dnp3-ffi v1.7.0 (/build/dnp3/ffi/dnp3-ffi)|enable-tls,serial,tls +1dnp3 v1.7.0 (/build/dnp3/dnp3)|enable-tls,ffi,serial,sfio-rustls-config,tls,tokio-rustls,tokio-serial +2chrono v0.4.44|alloc,clock,default,iana-time-zone,js-sys,now,oldtime,std,wasm-bindgen,wasmbind,winapi,windows-link +3iana-time-zone v0.1.65|fallback +3num-traits v0.2.19| +4autocfg v1.5.0| +2scursor v0.2.0| +2sfio-rustls-config v0.4.0|crypto-ring,default +3pem v3.0.6|default,std +4base64 v0.22.1|alloc,std +3pkcs8 v0.10.2|alloc,encryption,pem,pkcs5,rand_core,std +4der v0.7.10|alloc,oid,pem,std,zeroize +5const-oid v0.9.6| +5pem-rfc7468 v0.7.0|alloc +6base64ct v1.8.3|alloc +5zeroize v1.8.2|alloc,default +4pkcs5 v0.7.1|alloc,pbes2 +5aes v0.8.4| +6cfg-if v1.0.4| +6cipher v0.4.4|block-padding +7crypto-common v0.1.7| +8generic-array v0.14.7|more_lengths +9typenum v1.19.0| +9version_check v0.9.5| +8typenum v1.19.0| +7inout v0.1.4|block-padding +8block-padding v0.3.3| +9generic-array v0.14.7|more_lengths (*) +8generic-array v0.14.7|more_lengths (*) +6cpufeatures v0.2.17| +5cbc v0.1.2|block-padding,default +6cipher v0.4.4|block-padding (*) +5der v0.7.10|alloc,oid,pem,std,zeroize (*) +5pbkdf2 v0.12.2|default,hmac +6digest v0.10.7|block-buffer,core-api,default,mac,subtle +7block-buffer v0.10.4| +8generic-array v0.14.7|more_lengths (*) +7crypto-common v0.1.7| (*) +7subtle v2.6.1| +6hmac v0.12.1| +7digest v0.10.7|block-buffer,core-api,default,mac,subtle (*) +5scrypt v0.11.0| +6pbkdf2 v0.12.2|default,hmac (*) +6salsa20 v0.10.2| +7cipher v0.4.4|block-padding (*) +6sha2 v0.10.9| +7cfg-if v1.0.4| +7cpufeatures v0.2.17| +7digest v0.10.7|block-buffer,core-api,default,mac,subtle (*) +5sha2 v0.10.9| (*) +5spki v0.7.3|alloc,pem,std +6der v0.7.10|alloc,oid,pem,std,zeroize (*) +4rand_core v0.6.4| +4spki v0.7.3|alloc,pem,std (*) +3rustls v0.23.45|log,logging,ring,std,tls12 +4log v0.4.29|std +4once_cell v1.21.4|alloc,default,race,std +4ring v0.17.14|alloc,default,dev_urandom_fallback +5cfg-if v1.0.4| +5getrandom v0.2.17| +6cfg-if v1.0.4| +6libc v0.2.185|default,extra_traits,std +5untrusted v0.9.0| +5cc v1.2.60| +6find-msvc-tools v0.1.9| +6shlex v1.3.0|default,std +4rustls-pki-types v1.14.0|alloc,default,std +5zeroize v1.8.2|alloc,default +4rustls-webpki v0.103.15|alloc,ring,std +5ring v0.17.14|alloc,default,dev_urandom_fallback (*) +5rustls-pki-types v1.14.0|alloc,default,std (*) +5untrusted v0.9.0| +4subtle v2.6.1| +4zeroize v1.8.2|alloc,default +3rustls-pki-types v1.14.0|alloc,default,std (*) +3rustls-webpki v0.103.15|alloc,ring,std (*) +3rx509 v0.2.1| +2tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros +3bytes v1.11.1|default,std +3libc v0.2.185|default,extra_traits,std +3mio v1.2.0|default,log,net,os-ext,os-poll +4libc v0.2.185|default,extra_traits,std +4log v0.4.29|std +3pin-project-lite v0.2.17| +3socket2 v0.6.3|all +4libc v0.2.185|default,extra_traits,std +3tokio-macros v2.7.0 (proc-macro)| +4proc-macro2 v1.0.106|default,proc-macro +5unicode-ident v1.0.24| +4quote v1.0.45|default,proc-macro +5proc-macro2 v1.0.106|default,proc-macro (*) +4syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut +5proc-macro2 v1.0.106|default,proc-macro (*) +5quote v1.0.45|default,proc-macro (*) +5unicode-ident v1.0.24| +2tokio-rustls v0.26.4|tls12 +3rustls v0.23.45|log,logging,ring,std,tls12 (*) +3tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +2tokio-serial v5.4.5| +3cfg-if v1.0.4| +3futures v0.3.32|alloc,async-await,default,executor,futures-executor,std +4futures-channel v0.3.32|alloc,futures-sink,sink,std +5futures-core v0.3.32|alloc,std +5futures-sink v0.3.32|alloc,std +4futures-core v0.3.32|alloc,std +4futures-executor v0.3.32|std +5futures-core v0.3.32|alloc,std +5futures-task v0.3.32|alloc,std +5futures-util v0.3.32|alloc,async-await,async-await-macro,channel,futures-channel,futures-io,futures-macro,futures-sink,io,memchr,sink,slab,std +6futures-channel v0.3.32|alloc,futures-sink,sink,std (*) +6futures-core v0.3.32|alloc,std +6futures-io v0.3.32|std +6futures-macro v0.3.32 (proc-macro)| +7proc-macro2 v1.0.106|default,proc-macro (*) +7quote v1.0.45|default,proc-macro (*) +7syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut (*) +6futures-sink v0.3.32|alloc,std +6futures-task v0.3.32|alloc,std +6memchr v2.8.0|alloc,default,std +6pin-project-lite v0.2.17| +6slab v0.4.12|std +4futures-io v0.3.32|std +4futures-sink v0.3.32|alloc,std +4futures-task v0.3.32|alloc,std +4futures-util v0.3.32|alloc,async-await,async-await-macro,channel,futures-channel,futures-io,futures-macro,futures-sink,io,memchr,sink,slab,std (*) +3log v0.4.29|std +3mio-serial v5.0.6| +4log v0.4.29|std +4mio v1.2.0|default,log,net,os-ext,os-poll (*) +4nix v0.29.0|default,term +5bitflags v2.11.1| +5cfg-if v1.0.4| +5libc v0.2.185|default,extra_traits,std +5cfg_aliases v0.2.1| +4serialport v4.9.0| +5bitflags v2.11.1| +5cfg-if v1.0.4| +5nix v0.26.4|fs,ioctl,poll,process,signal,term +6bitflags v1.3.2|default +6cfg-if v1.0.4| +6libc v0.2.185|default,extra_traits,std +5scopeguard v1.2.0|default,use_std +5unescaper v0.1.8| +6thiserror v2.0.18|default,std +7thiserror-impl v2.0.18 (proc-macro)| +8proc-macro2 v1.0.106|default,proc-macro (*) +8quote v1.0.45|default,proc-macro (*) +8syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut (*) +3serialport v4.9.0| (*) +3tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +2tracing v0.1.44|attributes,default,std,tracing-attributes +3pin-project-lite v0.2.17| +3tracing-attributes v0.1.31 (proc-macro)| +4proc-macro2 v1.0.106|default,proc-macro (*) +4quote v1.0.45|default,proc-macro (*) +4syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut (*) +3tracing-core v0.1.36|default,once_cell,std +4once_cell v1.21.4|alloc,default,race,std +2xxhash-rust v0.8.15|xxh64 +1lazy_static v1.5.0| +1num_cpus v1.17.0| +2libc v0.2.185|default,extra_traits,std +1sfio-promise v0.2.0| +1tokio v1.52.1|bytes,default,io-std,io-util,libc,macros,mio,net,rt,rt-multi-thread,socket2,sync,time,tokio-macros (*) +1tracing v0.1.44|attributes,default,std,tracing-attributes (*) +1tracing-core v0.1.36|default,once_cell,std (*) +1tracing-subscriber v0.3.23|alloc,ansi,chrono,default,fmt,json,nu-ansi-term,registry,serde,serde_json,sharded-slab,smallvec,std,thread_local,tracing-log,tracing-serde +2chrono v0.4.44|alloc,clock,default,iana-time-zone,js-sys,now,oldtime,std,wasm-bindgen,wasmbind,winapi,windows-link (*) +2nu-ansi-term v0.50.3|default,std +2serde v1.0.228|default,std +3serde_core v1.0.228|result,std +2serde_json v1.0.149|default,std +3itoa v1.0.18| +3memchr v2.8.0|alloc,default,std +3serde_core v1.0.228|result,std +3zmij v1.0.21| +2sharded-slab v0.1.7| +3lazy_static v1.5.0| +2smallvec v1.15.1| +2thread_local v1.1.9| +3cfg-if v1.0.4| +2tracing-core v0.1.36|default,once_cell,std (*) +2tracing-log v0.2.0|log-tracer,std +3log v0.4.29|std +3once_cell v1.21.4|alloc,default,race,std +3tracing-core v0.1.36|default,once_cell,std (*) +2tracing-serde v0.2.0| +3serde v1.0.228|default,std (*) +3tracing-core v0.1.36|default,once_cell,std (*) +1dnp3-schema v1.7.0 (/build/dnp3/ffi/dnp3-schema)| +2oo-bindgen v0.8.8| +3backtrace v0.3.76|default,std +4addr2line v0.25.1| +5gimli v0.32.3|read,read-core +4cfg-if v1.0.4| +4libc v0.2.185| +4miniz_oxide v0.8.9| +5adler2 v2.0.1| +4object v0.37.3|archive,coff,elf,macho,pe,read_core,unaligned,xcoff +5memchr v2.8.0|alloc,std +4rustc-demangle v0.1.27| +3clap v4.6.1|color,default,derive,error-context,help,std,suggestions,usage +4clap_builder v4.6.0|color,error-context,help,std,suggestions,usage +5anstream v1.0.0|auto,default,wincon +6anstyle v1.0.14|default,std +6anstyle-parse v1.0.0|default,utf8 +7utf8parse v0.2.2|default +6anstyle-query v1.1.5| +6colorchoice v1.0.5| +6is_terminal_polyfill v1.70.2|default +6utf8parse v0.2.2|default +5anstyle v1.0.14|default,std +5clap_lex v1.1.0| +5strsim v0.11.1| +4clap_derive v4.6.1 (proc-macro)|default +5heck v0.5.0| +5proc-macro2 v1.0.106|default,proc-macro (*) +5quote v1.0.45|default,proc-macro (*) +5syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut (*) +3dunce v1.0.5| +3heck v0.5.0| +3lazy_static v1.5.0| +3platforms v2.0.0|default,std +3regex v1.12.3|default,perf,perf-backtrack,perf-cache,perf-dfa,perf-inline,perf-literal,perf-onepass,std,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment +4aho-corasick v1.1.4|perf-literal,std +5memchr v2.8.0|alloc,std +4memchr v2.8.0|alloc,std +4regex-automata v0.4.14|alloc,dfa-onepass,hybrid,meta,nfa-backtrack,nfa-pikevm,nfa-thompson,perf-inline,perf-literal,perf-literal-multisubstring,perf-literal-substring,std,syntax,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment,unicode-word-boundary +5aho-corasick v1.1.4|perf-literal,std (*) +5memchr v2.8.0|alloc,std +5regex-syntax v0.8.10|default,std,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment +4regex-syntax v0.8.10|default,std,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment +3semver v1.0.28|default,std +3serde v1.0.228|default,derive,serde_derive,std +4serde_core v1.0.228|result,std +4serde_derive v1.0.228 (proc-macro)|default +5proc-macro2 v1.0.106|default,proc-macro (*) +5quote v1.0.45|default,proc-macro (*) +5syn v2.0.117|clone-impls,default,derive,extra-traits,full,parsing,printing,proc-macro,visit-mut (*) +3serde_json v1.0.149|default,std +4itoa v1.0.18| +4memchr v2.8.0|alloc,std +4serde_core v1.0.228|result,std +4zmij v1.0.21| +3thiserror v2.0.18|default,std +4thiserror-impl v2.0.18 (proc-macro)| (*) +3tracing v0.1.44|attributes,default,std,tracing-attributes +4pin-project-lite v0.2.17| +4tracing-attributes v0.1.31 (proc-macro)| (*) +4tracing-core v0.1.36|once_cell,std +5once_cell v1.21.4|alloc,default,race,std +2sfio-tokio-ffi v0.9.0| +3oo-bindgen v0.8.8| (*) +2sfio-tracing-ffi v0.9.0| +3oo-bindgen v0.8.8| (*) +1oo-bindgen v0.8.8| (*) +1sfio-tokio-ffi v0.9.0| (*) +1sfio-tracing-ffi v0.9.0| (*) diff --git a/allow-list/tests/fixtures/workspace/Cargo.lock b/allow-list/tests/fixtures/workspace/Cargo.lock new file mode 100644 index 0000000..6e29901 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/Cargo.lock @@ -0,0 +1,60 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "alias-target" +version = "0.1.0" + +[[package]] +name = "app" +version = "0.1.0" +dependencies = [ + "alias-target", + "common", + "optdep", + "pm", + "shared", + "tool", + "unixonly", + "winonly", +] + +[[package]] +name = "common" +version = "0.1.0" + +[[package]] +name = "optdep" +version = "0.1.0" + +[[package]] +name = "pm" +version = "0.1.0" +dependencies = [ + "pmonly", + "shared", +] + +[[package]] +name = "pmonly" +version = "0.1.0" + +[[package]] +name = "shared" +version = "0.1.0" + +[[package]] +name = "tool" +version = "0.1.0" +dependencies = [ + "common", +] + +[[package]] +name = "unixonly" +version = "0.1.0" + +[[package]] +name = "winonly" +version = "0.1.0" diff --git a/allow-list/tests/fixtures/workspace/Cargo.toml b/allow-list/tests/fixtures/workspace/Cargo.toml new file mode 100644 index 0000000..35365af --- /dev/null +++ b/allow-list/tests/fixtures/workspace/Cargo.toml @@ -0,0 +1,5 @@ +# A small workspace exercising the cases the build-log + cargo tree reader must classify; +# built for real by the tests in `allow-list/src/fixture_tests.rs`. +[workspace] +resolver = "2" +members = ["app", "shared", "common", "pm", "pmonly", "tool", "alias-target", "optdep", "winonly", "unixonly"] diff --git a/allow-list/tests/fixtures/workspace/alias-target/Cargo.toml b/allow-list/tests/fixtures/workspace/alias-target/Cargo.toml new file mode 100644 index 0000000..5af7346 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/alias-target/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "alias-target" +version = "0.1.0" +edition = "2021" +publish = false + +# a custom library name, used through a renamed optional dependency +[lib] +name = "aliaslib" diff --git a/allow-list/tests/fixtures/workspace/alias-target/src/lib.rs b/allow-list/tests/fixtures/workspace/alias-target/src/lib.rs new file mode 100644 index 0000000..efc0d13 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/alias-target/src/lib.rs @@ -0,0 +1 @@ +pub fn alias() {} diff --git a/allow-list/tests/fixtures/workspace/app/Cargo.toml b/allow-list/tests/fixtures/workspace/app/Cargo.toml new file mode 100644 index 0000000..235c330 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/app/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "app" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["rlib", "cdylib"] + +[dependencies] +shared = { path = "../shared", features = ["target-feat"] } +common = { path = "../common" } +pm = { path = "../pm" } +optdep = { path = "../optdep", optional = true } +alias = { package = "alias-target", path = "../alias-target", optional = true } + +[target.'cfg(unix)'.dependencies] +unixonly = { path = "../unixonly" } + +[target.'cfg(windows)'.dependencies] +winonly = { path = "../winonly" } + +[build-dependencies] +tool = { path = "../tool" } + +[features] +default = ["use-alias"] +use-alias = ["dep:alias"] +extra = ["dep:optdep"] diff --git a/allow-list/tests/fixtures/workspace/app/build.rs b/allow-list/tests/fixtures/workspace/app/build.rs new file mode 100644 index 0000000..d3a101a --- /dev/null +++ b/allow-list/tests/fixtures/workspace/app/build.rs @@ -0,0 +1,3 @@ +fn main() { + tool::run(); +} diff --git a/allow-list/tests/fixtures/workspace/app/src/lib.rs b/allow-list/tests/fixtures/workspace/app/src/lib.rs new file mode 100644 index 0000000..6d7c2ae --- /dev/null +++ b/allow-list/tests/fixtures/workspace/app/src/lib.rs @@ -0,0 +1,8 @@ +pm::nothing!(); + +pub fn app() { + shared::shared(); + common::common(); + #[cfg(feature = "use-alias")] + alias::alias(); +} diff --git a/allow-list/tests/fixtures/workspace/common/Cargo.toml b/allow-list/tests/fixtures/workspace/common/Cargo.toml new file mode 100644 index 0000000..1fa2832 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/common/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "common" +version = "0.1.0" +edition = "2021" +publish = false + diff --git a/allow-list/tests/fixtures/workspace/common/src/lib.rs b/allow-list/tests/fixtures/workspace/common/src/lib.rs new file mode 100644 index 0000000..8e56fd1 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/common/src/lib.rs @@ -0,0 +1 @@ +pub fn common() {} diff --git a/allow-list/tests/fixtures/workspace/optdep/Cargo.toml b/allow-list/tests/fixtures/workspace/optdep/Cargo.toml new file mode 100644 index 0000000..68742a9 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/optdep/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "optdep" +version = "0.1.0" +edition = "2021" +publish = false + diff --git a/allow-list/tests/fixtures/workspace/optdep/src/lib.rs b/allow-list/tests/fixtures/workspace/optdep/src/lib.rs new file mode 100644 index 0000000..6123e66 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/optdep/src/lib.rs @@ -0,0 +1 @@ +pub fn optdep() {} diff --git a/allow-list/tests/fixtures/workspace/pm/Cargo.toml b/allow-list/tests/fixtures/workspace/pm/Cargo.toml new file mode 100644 index 0000000..8814b9b --- /dev/null +++ b/allow-list/tests/fixtures/workspace/pm/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "pm" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +proc-macro = true + +[dependencies] +# the same package as a runtime dependency of `app`, but with different features (host variant) +shared = { path = "../shared", features = ["host-feat"] } +pmonly = { path = "../pmonly" } diff --git a/allow-list/tests/fixtures/workspace/pm/src/lib.rs b/allow-list/tests/fixtures/workspace/pm/src/lib.rs new file mode 100644 index 0000000..79329fe --- /dev/null +++ b/allow-list/tests/fixtures/workspace/pm/src/lib.rs @@ -0,0 +1,8 @@ +use proc_macro::TokenStream; + +#[proc_macro] +pub fn nothing(_input: TokenStream) -> TokenStream { + shared::shared(); + pmonly::pmonly(); + TokenStream::new() +} diff --git a/allow-list/tests/fixtures/workspace/pmonly/Cargo.toml b/allow-list/tests/fixtures/workspace/pmonly/Cargo.toml new file mode 100644 index 0000000..94aade2 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/pmonly/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "pmonly" +version = "0.1.0" +edition = "2021" +publish = false + diff --git a/allow-list/tests/fixtures/workspace/pmonly/src/lib.rs b/allow-list/tests/fixtures/workspace/pmonly/src/lib.rs new file mode 100644 index 0000000..d668ba6 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/pmonly/src/lib.rs @@ -0,0 +1 @@ +pub fn pmonly() {} diff --git a/allow-list/tests/fixtures/workspace/shared/Cargo.toml b/allow-list/tests/fixtures/workspace/shared/Cargo.toml new file mode 100644 index 0000000..af8e71d --- /dev/null +++ b/allow-list/tests/fixtures/workspace/shared/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "shared" +version = "0.1.0" +edition = "2021" +publish = false + +[features] +target-feat = [] +host-feat = [] diff --git a/allow-list/tests/fixtures/workspace/shared/src/lib.rs b/allow-list/tests/fixtures/workspace/shared/src/lib.rs new file mode 100644 index 0000000..b1d5c4b --- /dev/null +++ b/allow-list/tests/fixtures/workspace/shared/src/lib.rs @@ -0,0 +1 @@ +pub fn shared() {} diff --git a/allow-list/tests/fixtures/workspace/tool/Cargo.toml b/allow-list/tests/fixtures/workspace/tool/Cargo.toml new file mode 100644 index 0000000..4e47777 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/tool/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "tool" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +common = { path = "../common" } diff --git a/allow-list/tests/fixtures/workspace/tool/src/lib.rs b/allow-list/tests/fixtures/workspace/tool/src/lib.rs new file mode 100644 index 0000000..45338a3 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/tool/src/lib.rs @@ -0,0 +1 @@ +pub fn run() { common::common(); } diff --git a/allow-list/tests/fixtures/workspace/unixonly/Cargo.toml b/allow-list/tests/fixtures/workspace/unixonly/Cargo.toml new file mode 100644 index 0000000..d900923 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/unixonly/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "unixonly" +version = "0.1.0" +edition = "2021" +publish = false + diff --git a/allow-list/tests/fixtures/workspace/unixonly/src/lib.rs b/allow-list/tests/fixtures/workspace/unixonly/src/lib.rs new file mode 100644 index 0000000..4a9d28b --- /dev/null +++ b/allow-list/tests/fixtures/workspace/unixonly/src/lib.rs @@ -0,0 +1 @@ +pub fn unixonly() {} diff --git a/allow-list/tests/fixtures/workspace/winonly/Cargo.toml b/allow-list/tests/fixtures/workspace/winonly/Cargo.toml new file mode 100644 index 0000000..b5c9cc8 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/winonly/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "winonly" +version = "0.1.0" +edition = "2021" +publish = false + diff --git a/allow-list/tests/fixtures/workspace/winonly/src/lib.rs b/allow-list/tests/fixtures/workspace/winonly/src/lib.rs new file mode 100644 index 0000000..59e0d44 --- /dev/null +++ b/allow-list/tests/fixtures/workspace/winonly/src/lib.rs @@ -0,0 +1 @@ +pub fn winonly() {} From ce3653e5cd1067425fd04ef3160c8becf27c0a08 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 12:45:23 -0700 Subject: [PATCH 02/12] Document the build-evidence workflow; CI; release 0.3.0 - README: what the tool does, the producer recipe for the build evidence, commands, allowed.json rules, and the guarantees and limits of the cross-checks - CHANGELOG entry for 0.3.0 (breaking changes to gen-licenses-log*) - GitHub Actions: fmt, clippy, tests (including the real-Cargo fixture), and CycloneDX 1.5 schema validation of an SBOM with a pinned, checksum-verified cyclonedx-cli --- .github/workflows/ci.yml | 33 ++++++++++ CHANGELOG.md | 39 +++++++++++ Cargo.lock | 2 +- README.md | 137 +++++++++++++++++++++++++++++++++++++++ allow-list/Cargo.toml | 2 +- 5 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 README.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c197c68 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,33 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + - name: Format + run: cargo fmt --all --check + - name: Clippy + run: cargo clippy --all-targets + - name: Test + # includes tests that build tests/fixtures/workspace with the installed Cargo + run: cargo test + - name: Validate an SBOM against the CycloneDX 1.5 schema + env: + CYCLONEDX_CLI_VERSION: v0.33.1 + CYCLONEDX_CLI_SHA256: bfc8b2538da86fe239bc53658bbb63c1c8c510a293c1e6891aa5bea5d3c58746 + run: | + curl -sSLo cyclonedx https://github.com/CycloneDX/cyclonedx-cli/releases/download/$CYCLONEDX_CLI_VERSION/cyclonedx-linux-x64 + echo "$CYCLONEDX_CLI_SHA256 cyclonedx" | sha256sum -c + chmod +x cyclonedx + F=allow-list/tests/fixtures/dnp3 + cargo run -- gen-sbom-log-dir -l $F/targets --root-package dnp3-ffi -m $F/metadata.json -c $F/allowed.json --lockfile $F/Cargo.lock > sbom.json + ./cyclonedx validate --input-file sbom.json --input-version v1_5 --fail-on-errors diff --git a/CHANGELOG.md b/CHANGELOG.md index b91cc43..ff23e20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,45 @@ Notable changes to the `allow-list` tool, newest first. Version numbers mark CLI releases (so a consumer can pin a specific build, e.g. `cargo install --tag`); they are not a library API compatibility promise. +## [0.3.0] - 2026-10-09 + +Breaking: `gen-licenses-log` and `gen-licenses-log-dir` take new inputs and arguments, and +their output changes (see below). See the README for how to produce the inputs. + +### Added + +- `gen-sbom-log` and `gen-sbom-log-dir`: a CycloneDX 1.5 JSON SBOM from the same validated + inventory as the license report. Runtime packages have `scope: required`, build-time + packages `scope: excluded`; licenses are the declared SPDX expressions (commercial license + for first-party and vendor packages); `--lockfile` adds SHA-256 hashes; dependencies are + the observed package edges; `--omit-serial-number` with `SOURCE_DATE_EPOCH` gives + reproducible output. +- Every compiled package is classified as runtime or build-time by `cargo tree` (Cargo's own + resolver), cross-checked against the build log: packages and (package, features) variants + must match exactly. Build logs are validated (successful `build-finished`, no test, example + or bench artifacts, a product artifact for the root). +- `allowed.json` is enforced as an approval list instead of a filter: every package outside + the workspace must be in exactly one of `third_party`, `vendor`, `build_only`; a + `build_only` package that becomes linked fails; reviewed licenses of shipped `third_party` + packages are checked against the declared SPDX expression in both directions. +- `embedded` flag on `third_party` / `vendor` entries, `commercial_license`, and the + `Apache2` license. + +### Changed + +- `gen-licenses-log` / `gen-licenses-log-dir` require `--root-package` and the two + `cargo tree` outputs per target (`--tree-path`, `--runtime-tree-path`; fixed names + `build.json`, `tree.txt`, `runtime-tree.txt` in each target directory for the `-dir` + variant, which no longer takes `--log-file`). `cargo metadata` should be generated with + `--all-features`. +- Their report now lists only packages linked into the product: build-time packages + (proc-macros and their dependencies, build-script dependencies) are no longer listed, and + first-party crates are matched by name and version instead of being skipped. + +### Deprecated + +- `gen-licenses` / `gen-licenses-dir` (cargo-cyclonedx input). Their output is unchanged. + ## [0.2.1] - 2026-07-22 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 1bdf775..00435f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,7 +13,7 @@ dependencies = [ [[package]] name = "allow-list" -version = "0.2.1" +version = "0.3.0" dependencies = [ "anyhow", "cargo_metadata", diff --git a/README.md b/README.md new file mode 100644 index 0000000..e724406 --- /dev/null +++ b/README.md @@ -0,0 +1,137 @@ +# bom-tools + +`allow-list` produces the third-party license report (`third-party-licenses.txt`) and a +CycloneDX 1.5 SBOM for a Rust product, from the evidence of the build that produced it, and +checks every dependency against a reviewed allow-list (`allowed.json`). + +```sh +cargo install --git https://github.com/stepfunc/bom-tools.git --tag 0.3.0 +``` + +## How it works + +The scope of the report and the SBOM is what the build actually compiled, never what the +dependency graph could contain. For each target the product is built for: + +1. the `cargo build --message-format json` log proves which packages compiled, with which + features; +2. `cargo tree` (Cargo's own resolver) tells which of them are linked into the product + (**runtime**) and which only run while building it (**build time**: build scripts, + proc-macros and their dependencies); +3. the two are cross-checked, so evidence from a different invocation fails loudly. + +Targets are merged (a package that is runtime on any target is runtime), resolved against +`cargo metadata` for licenses and sources, and approved against `allowed.json`. The license +report and the SBOM are two views of that one validated inventory: the report lists exactly +the runtime `third_party` packages, which are exactly the SBOM's `required` third-party +components. + +## Producing the build evidence + +Run these in the **same job and environment as the build** (same host, toolchain, checkout, +lockfile and Cargo configuration), with **one shared argument string**, and keep the files +only if all three succeed: + +```sh +ARGS="-p dnp3-ffi --target $TARGET --no-default-features --features serial,tls --locked" +TREE_FMT="--prefix depth --color never --format {p}|{f}" +mkdir -p evidence/$TARGET +cargo build --release $ARGS --message-format json > evidence/$TARGET/build.json +cargo tree $ARGS -e normal,build $TREE_FMT > evidence/$TARGET/tree.txt +cargo tree $ARGS -e normal,no-proc-macro $TREE_FMT > evidence/$TARGET/runtime-tree.txt +``` + +Use `cross build` instead of `cargo build` for cross builds; the trees can run on the runner +when its host triple equals the container's. The trees must come from the build's host: +build dependencies are resolved for the host, so a tree produced on a Linux packaging runner +does not describe a build that ran on Windows. + +Once, anywhere, from the same checkout: + +```sh +cargo metadata --format-version 1 --all-features --locked > metadata.json +``` + +This is only a dictionary of package details (license, source, workspace membership); it +never decides scope or roles. + +## Commands + +```sh +# one target +allow-list gen-licenses-log -g build.json --tree-path tree.txt --runtime-tree-path runtime-tree.txt \ + --root-package dnp3-ffi -m metadata.json -c allowed.json > third-party-licenses.txt + +# every target, one subdirectory each (build.json, tree.txt, runtime-tree.txt) +allow-list gen-licenses-log-dir -l evidence --root-package dnp3-ffi -m metadata.json -c allowed.json \ + > third-party-licenses.txt +allow-list gen-sbom-log-dir -l evidence --root-package dnp3-ffi -m metadata.json -c allowed.json \ + --lockfile Cargo.lock > dnp3-ffi-1.7.0.cdx.json +``` + +`gen-sbom-log` / `gen-sbom-log-dir` take the same inputs plus: + +- `--lockfile `: add each crates.io package's SHA-256 (the `.crate` archive hash); +- `--omit-serial-number`: with `SOURCE_DATE_EPOCH` (used as the timestamp), output is + byte-for-byte reproducible. + +`gen-licenses` / `gen-licenses-dir` read `cargo cyclonedx` SBOMs. They are **deprecated**: +`cargo cyclonedx` describes the dependency graph for its own feature selection, not the +features the product was built with. + +## `allowed.json` + +```jsonc +{ + // approved to run at build time only; license not reviewed + "build_only": ["cc", "syn"], + // licensed to the customer by the vendor under its commercial license + "vendor": { + "sfio-tokio-ffi": { "url": "https://github.com/stepfunc/tokio-ffi", "embedded": true } + }, + // open-source, license reviewed + "third_party": { + "ring": { "id": "ring", "source": "crates.io", "licenses": ["Apache2", { "ISC": { "copyright": "NotPresent" } }] } + }, + // names the license of first-party and vendor packages in the SBOM + "commercial_license": { "name": "Step Function I/O License Agreement", "url": "https://..." } +} +``` + +Rules, checked on every run (all violations are reported together): + +- every compiled package outside the workspace is in **exactly one** list; +- a runtime package must be in `third_party` or `vendor`; a `build_only` package that becomes + linked into the product is an error; +- a build-time package may be in any list; +- only crates.io and workspace packages are supported; +- for runtime `third_party` packages, every reviewed license must be part of the package's + declared SPDX `license`, and the reviewed licenses must satisfy it (reviewed `MIT` satisfies + `MIT OR Apache-2.0` but not `MIT AND Apache-2.0`). + +`embedded: true` marks a build-time dependency whose own code ships anyway (for example a build +script that copies source it provides into the product); it is treated as runtime, its +dependencies are not. License names: `MIT`, `ISC`, `BSD3` (with `copyright`), `Apache2`, +`OpenSSL`, `BSLv1`, `MPLv2`, `UnicodeDFS2016`. + +## Guarantees and limits + +The cross-checks prove that the full `cargo tree` has exactly the packages, and exactly the +(package, enabled features) variants, of the build log, and that the runtime tree is part of +the full tree. That catches different feature flags, wider builds and dropped artifacts whose +features differ from the package's other variants. + +Not detected, so guaranteed only by producing the files as above: + +- a truncated tree file; +- a dropped artifact whose features equal another variant of the same package (e.g. the host + and target builds of a package with no features); +- differences that leave the variant sets unchanged (Cargo does not guarantee `cargo tree` + matches a build exactly). + +Supported builds: `cargo build` of a library or binary (`cargo check`, tests, examples and +benches are rejected), crates.io and workspace packages. Not supported: build-script overrides, +`-Zbuild-std`, and non-Rust components inside `-sys` crates beyond the crate's declared license. + +When Cargo's SBOM precursor files (`-Z sbom`) are stable they will replace the build log and +`cargo tree` inputs ([#8](https://github.com/stepfunc/bom-tools/issues/8)). diff --git a/allow-list/Cargo.toml b/allow-list/Cargo.toml index eb3120c..64fa7ba 100644 --- a/allow-list/Cargo.toml +++ b/allow-list/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "allow-list" -version = "0.2.1" +version = "0.3.0" edition = "2021" [lints] From 8218858f979f6ad0c66533623c31cfd2978dfc95 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 12:52:09 -0700 Subject: [PATCH 03/12] Close fail-open paths found in review; strengthen tests - the root must be a workspace member (it is never approved) - the root's product artifact is matched by full package identity, so a dependency with the same name cannot satisfy it - build log lines are parsed whole; nothing may follow build-finished - lockfile checksums must be 64 hex digits - third_party entries are sanity-checked whatever the package's role - single-target flags are --log/-g, --tree, --runtime-tree - tests: reader negatives (dropped/extra packages, feature mismatch, runtime tree from other arguments, roots, product artifact), direct TargetGraph SBOM tests (per-version hashes, bom-ref collision, license encoding), exact per-version hash and report/SBOM invariant checks, a host-only feature dependency in the Cargo fixture, Windows expectations, and a fresh fixture directory per run --- CHANGELOG.md | 2 +- README.md | 2 +- allow-list/src/approval.rs | 31 ++- allow-list/src/cli.rs | 14 +- allow-list/src/config.rs | 2 +- allow-list/src/fixture_tests.rs | 25 +- allow-list/src/golden_tests.rs | 55 +++- allow-list/src/input/build_log.rs | 138 ++++++---- allow-list/src/input/mod.rs | 114 +++++++- allow-list/src/inventory.rs | 14 + allow-list/src/sbom.rs | 244 +++++++++++++++--- .../tests/fixtures/workspace/Cargo.lock | 7 + .../tests/fixtures/workspace/Cargo.toml | 2 +- .../fixtures/workspace/hostextra/Cargo.toml | 5 + .../fixtures/workspace/hostextra/src/lib.rs | 1 + .../fixtures/workspace/shared/Cargo.toml | 6 +- 16 files changed, 547 insertions(+), 115 deletions(-) create mode 100644 allow-list/tests/fixtures/workspace/hostextra/Cargo.toml create mode 100644 allow-list/tests/fixtures/workspace/hostextra/src/lib.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index ff23e20..559284a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ their output changes (see below). See the README for how to produce the inputs. ### Changed - `gen-licenses-log` / `gen-licenses-log-dir` require `--root-package` and the two - `cargo tree` outputs per target (`--tree-path`, `--runtime-tree-path`; fixed names + `cargo tree` outputs per target (`--tree`, `--runtime-tree`, and `--log` for `-g`; fixed names `build.json`, `tree.txt`, `runtime-tree.txt` in each target directory for the `-dir` variant, which no longer takes `--log-file`). `cargo metadata` should be generated with `--all-features`. diff --git a/README.md b/README.md index e724406..9d72e11 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ never decides scope or roles. ```sh # one target -allow-list gen-licenses-log -g build.json --tree-path tree.txt --runtime-tree-path runtime-tree.txt \ +allow-list gen-licenses-log -g build.json --tree tree.txt --runtime-tree runtime-tree.txt \ --root-package dnp3-ffi -m metadata.json -c allowed.json > third-party-licenses.txt # every target, one subdirectory each (build.json, tree.txt, runtime-tree.txt) diff --git a/allow-list/src/approval.rs b/allow-list/src/approval.rs index 21d0cf9..9620fba 100644 --- a/allow-list/src/approval.rs +++ b/allow-list/src/approval.rs @@ -126,26 +126,24 @@ fn approve<'c>(component: &Component, config: &'c Config) -> Result } }; + if let Approval::ThirdParty(approved) = approval { + check_entry(name, approved)?; + } match approval { Approval::BuildOnly if runtime => Err( "is approved only as a build tool (`build_only`) but now ships in the product" .to_string(), ), Approval::ThirdParty(approved) if runtime => { - check_reviewed_license(name, approved, &component.license)?; + check_reviewed_license(approved, &component.license)?; Ok(approval) } _ => Ok(approval), } } -/// The reviewed licenses must still be part of the declared expression (no stale extras) and -/// must satisfy it (no newly mandatory licenses) -fn check_reviewed_license( - name: &str, - approved: &ApprovedPackage, - declared: &DeclaredLicense, -) -> Result<(), String> { +/// A `third_party` entry must be well formed, however the package is used +fn check_entry(name: &str, approved: &ApprovedPackage) -> Result<(), String> { if approved.id != name { return Err(format!( "`third_party` entry is keyed `{name}` but has id `{}`", @@ -162,6 +160,15 @@ fn check_reviewed_license( { return Err("`third_party` entry has an `Unknown` license".to_string()); } + Ok(()) +} + +/// The reviewed licenses must still be part of the declared expression (no stale extras) and +/// must satisfy it (no newly mandatory licenses) +fn check_reviewed_license( + approved: &ApprovedPackage, + declared: &DeclaredLicense, +) -> Result<(), String> { let expression = match declared { DeclaredLicense::Valid(expression) => expression, DeclaredLicense::Missing => { @@ -350,7 +357,13 @@ mod tests { let mut json = empty(); json["third_party"]["x"] = serde_json::json!({"id": "x", "source": "crates.io", "licenses": ["Unknown"]}); - assert!(check(&[("x", Some("MIT"), Role::Runtime)], &config(json)) + assert!( + check(&[("x", Some("MIT"), Role::Runtime)], &config(json.clone())) + .unwrap_err() + .contains("Unknown") + ); + // entries are checked however the package is used + assert!(check(&[("x", Some("MIT"), Role::BuildTime)], &config(json)) .unwrap_err() .contains("Unknown")); } diff --git a/allow-list/src/cli.rs b/allow-list/src/cli.rs index ea0d80b..b953d72 100644 --- a/allow-list/src/cli.rs +++ b/allow-list/src/cli.rs @@ -99,14 +99,14 @@ impl From for SbomOptions { #[derive(Args)] pub(crate) struct TargetFiles { /// path to the `cargo build --message-format json` log - #[clap(value_parser, long, short = 'g')] - log_path: PathBuf, + #[clap(value_parser, long, short = 'g', alias = "log-path")] + log: PathBuf, /// path to the `cargo tree -e normal,build --prefix depth --format '{p}|{f}'` output #[clap(value_parser, long)] - tree_path: PathBuf, + tree: PathBuf, /// path to the `cargo tree -e normal,no-proc-macro --prefix depth --format '{p}|{f}'` output #[clap(value_parser, long)] - runtime_tree_path: PathBuf, + runtime_tree: PathBuf, } /// The build evidence of several targets @@ -135,9 +135,9 @@ pub(crate) struct Common { impl TargetFiles { pub(crate) fn evidence(self, common: Common) -> Evidence { let target = TargetInput::LogAndTree { - log: self.log_path, - tree: self.tree_path, - runtime_tree: self.runtime_tree_path, + log: self.log, + tree: self.tree, + runtime_tree: self.runtime_tree, }; common.evidence(vec![target]) } diff --git a/allow-list/src/config.rs b/allow-list/src/config.rs index 4132750..ac0d10c 100644 --- a/allow-list/src/config.rs +++ b/allow-list/src/config.rs @@ -115,7 +115,7 @@ pub(crate) struct CommercialLicense { /// Represent a configuration file for a particular project #[derive(Serialize, Deserialize, Debug)] pub(crate) struct Config { - /// packages that are build-only dependencies, are not linked/distributed, and are ignored in the build log + /// packages approved for use at build time only (not linked or distributed); license not reviewed pub(crate) build_only: BTreeSet, /// packages that are licensed by the vendor and are distributed under a custom license pub(crate) vendor: BTreeMap, diff --git a/allow-list/src/fixture_tests.rs b/allow-list/src/fixture_tests.rs index 1eb7882..34bcf47 100644 --- a/allow-list/src/fixture_tests.rs +++ b/allow-list/src/fixture_tests.rs @@ -24,7 +24,14 @@ fn evidence() -> &'static Evidence { static EVIDENCE: OnceLock = OnceLock::new(); EVIDENCE.get_or_init(|| { let workspace = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/workspace"); - let dir = std::env::temp_dir().join(format!("allow-list-fixture-{}", std::process::id())); + let nanos = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_nanos(); + let dir = + std::env::temp_dir().join(format!("allow-list-fixture-{}-{nanos}", std::process::id())); + // start from an empty target directory, so every artifact is built by this run + let _ = std::fs::remove_dir_all(&dir); std::fs::create_dir_all(&dir).unwrap(); let host = host_triple(); let args = ["-p", "app", "--target", &host, "--locked", "--offline"]; @@ -158,15 +165,23 @@ fn cargo_classifies_runtime_and_build_time_packages() { // a runtime dependency also used (with different features) beneath a proc-macro ("shared", Role::Runtime), ("unixonly", Role::Runtime), + ("winonly", Role::Runtime), + // an optional dependency that only the host variant of `shared` enables: Cargo's + // resolver keeps host and target features apart, so it does not ship + ("hostextra", Role::BuildTime), ("pm", Role::BuildTime), ("pmonly", Role::BuildTime), ("tool", Role::BuildTime), ]); let expected: BTreeMap<&str, Role> = expected .into_iter() - .filter(|(name, _)| cfg!(unix) || *name != "unixonly") + .filter(|(name, _)| match *name { + "unixonly" => cfg!(unix), + "winonly" => cfg!(windows), + _ => true, + }) .collect(); - // `optdep` (disabled feature) and `winonly`/`unixonly` (other platform) never compile + // `optdep` (disabled feature) and the other platform's dependency never compile assert_eq!(roles(&graph), expected); } @@ -181,11 +196,15 @@ fn cargo_tree_edges_include_every_expansion() { ("app", "tool"), ("pm", "pmonly"), ("pm", "shared"), + ("shared", "hostextra"), ("tool", "common"), ]); if cfg!(unix) { expected.insert(("app", "unixonly")); } + if cfg!(windows) { + expected.insert(("app", "winonly")); + } assert_eq!(edges(&graph), expected); } diff --git a/allow-list/src/golden_tests.rs b/allow-list/src/golden_tests.rs index ac856fd..0711215 100644 --- a/allow-list/src/golden_tests.rs +++ b/allow-list/src/golden_tests.rs @@ -288,7 +288,18 @@ fn license_report_lists_exactly_the_shipped_third_party_crates() { for not_third_party in ["dnp3", "sfio-promise", "sfio-tokio-ffi"] { assert!(!crates.contains(not_third_party), "{not_third_party}"); } - assert_eq!(crates, sbom_required_third_party(&sbom_document())); + // the report and the SBOM are projections of the same inventory, down to every version + let mut reported = BTreeSet::new(); + let mut lines = report.lines(); + while let Some(line) = lines.next() { + if let Some(name) = line.strip_prefix("crate: ") { + let versions = lines.next().unwrap().strip_prefix("version(s): ").unwrap(); + for version in versions.split(", ") { + reported.insert((name.to_string(), version.to_string())); + } + } + } + assert_eq!(reported, sbom_required_third_party(&sbom_document())); } /// The SBOM of all targets, with a fixed timestamp and no serial number @@ -319,15 +330,20 @@ fn sbom_document() -> serde_json::Value { } /// Names of the `required` components whose license is an SPDX expression (third-party code) -fn sbom_required_third_party(bom: &serde_json::Value) -> BTreeSet<&str> { +fn sbom_required_third_party(bom: &serde_json::Value) -> BTreeSet<(String, String)> { let config: Config = load("allowed.json"); bom["components"] .as_array() .unwrap() .iter() .filter(|c| c["scope"] == "required") - .map(|c| c["name"].as_str().unwrap()) - .filter(|name| config.third_party.contains_key(*name)) + .filter(|c| config.third_party.contains_key(c["name"].as_str().unwrap())) + .map(|c| { + ( + c["name"].as_str().unwrap().to_string(), + c["version"].as_str().unwrap().to_string(), + ) + }) .collect() } @@ -369,10 +385,33 @@ fn sbom_scopes_licenses_hashes_and_edges() { ); assert!(component("dnp3").get("hashes").is_none()); - let lock = std::fs::read_to_string(fixture("Cargo.lock")).unwrap(); - let serde_hash = component("serde")["hashes"][0]["content"].as_str().unwrap(); - assert!(lock.contains(&format!("checksum = \"{serde_hash}\""))); - assert_eq!(component("serde")["hashes"][0]["alg"], "SHA-256"); + // every crates.io component carries the checksum of its own (name, version) lock entry + let lock: toml::Value = + toml::from_str(&std::fs::read_to_string(fixture("Cargo.lock")).unwrap()).unwrap(); + let locked: BTreeMap<(&str, &str), &str> = lock["package"] + .as_array() + .unwrap() + .iter() + .filter_map(|p| { + Some(( + (p["name"].as_str()?, p["version"].as_str()?), + p.get("checksum")?.as_str()?, + )) + }) + .collect(); + let mut hashed = 0; + for c in components { + let key = (c["name"].as_str().unwrap(), c["version"].as_str().unwrap()); + match locked.get(&key) { + Some(checksum) => { + assert_eq!(c["hashes"][0]["alg"], "SHA-256"); + assert_eq!(c["hashes"][0]["content"], *checksum, "{key:?}"); + hashed += 1; + } + None => assert!(c.get("hashes").is_none(), "{key:?}"), + } + } + assert!(hashed > 100); let depends_on = |from: &str, to: &str| { let from = format!("pkg:cargo/{from}@"); diff --git a/allow-list/src/input/build_log.rs b/allow-list/src/input/build_log.rs index 09610a2..9091317 100644 --- a/allow-list/src/input/build_log.rs +++ b/allow-list/src/input/build_log.rs @@ -1,12 +1,13 @@ //! Reader for `cargo build --message-format json` logs use super::{pkgid, Variant}; +use crate::graph::PackageKey; use anyhow::anyhow; use cargo_metadata::{Message, TargetKind}; use std::collections::BTreeSet; use std::io::BufRead; -/// Kinds of a root artifact that count as a shippable product +/// Kinds of artifact that count as a shippable product const PRODUCT_KINDS: [TargetKind; 6] = [ TargetKind::Lib, TargetKind::RLib, @@ -20,25 +21,52 @@ const PRODUCT_KINDS: [TargetKind; 6] = [ const NON_PRODUCT_KINDS: [TargetKind; 3] = [TargetKind::Example, TargetKind::Test, TargetKind::Bench]; -/// Read and validate a build log, returning the (package, features) variant of every compiled -/// artifact except build scripts. +/// What a build log proves +#[derive(Debug)] +pub(crate) struct BuildLog { + /// The (package, features) variant of every compiled artifact except build scripts + pub(crate) variants: BTreeSet, + /// Packages with a product artifact (a library or binary that is not only `.rmeta`) + pub(crate) products: BTreeSet, +} + +/// Read and validate a build log. /// -/// The log must come from a successful product build of `root`: it must end with a successful -/// `build-finished` message, contain no test/example/bench artifacts, and contain a non-`.rmeta` -/// product artifact for `root` (which rejects `cargo check`). -pub(crate) fn read(log: R, root: &str) -> Result, anyhow::Error> { +/// The log must come from a successful product build: every JSON line must be a complete +/// message, it must end with a successful `build-finished` message, and it must contain no +/// test/example/bench artifacts. +pub(crate) fn read(log: R) -> Result { let mut variants = BTreeSet::new(); + let mut products = BTreeSet::new(); let mut finished = None; - let mut root_product = false; - for message in Message::parse_stream(log) { - let message = message?; + for (index, line) in log.lines().enumerate() { + let line = line?; + let line = line.trim(); + let line_number = index + 1; if finished.is_some() { - if !matches!(message, Message::TextLine(_)) { - return Err(anyhow!("build log has messages after `build-finished`")); + if !line.is_empty() { + return Err(anyhow!( + "build log line {line_number}: content after `build-finished`" + )); } continue; } + if !line.starts_with('{') { + continue; + } + // parse the whole line, so that a truncated or concatenated message is an error + let value: serde_json::Value = serde_json::from_str(line) + .map_err(|err| anyhow!("build log line {line_number}: malformed message: {err}"))?; + // compiler diagnostics, build script output and future message kinds carry no scope + if !matches!( + value["reason"].as_str(), + Some("compiler-artifact" | "build-finished") + ) { + continue; + } + let message = serde_json::from_value(value) + .map_err(|err| anyhow!("build log line {line_number}: malformed message: {err}"))?; match message { Message::CompilerArtifact(artifact) => { if artifact.profile.test @@ -59,18 +87,17 @@ pub(crate) fn read(log: R, root: &str) -> Result, continue; } let key = pkgid::parse(&artifact.package_id.repr)?; - if key.name == root - && artifact - .target - .kind - .iter() - .any(|k| PRODUCT_KINDS.contains(k)) + let product = artifact + .target + .kind + .iter() + .any(|k| PRODUCT_KINDS.contains(k)) && artifact .filenames .iter() - .any(|f| f.extension() != Some("rmeta")) - { - root_product = true; + .any(|f| f.extension() != Some("rmeta")); + if product { + products.insert(key.clone()); } variants.insert(Variant { key, @@ -78,9 +105,6 @@ pub(crate) fn read(log: R, root: &str) -> Result, }); } Message::BuildFinished(status) => finished = Some(status.success), - Message::TextLine(line) if line.trim_start().starts_with('{') => { - return Err(anyhow!("build log contains a malformed message: {line}")); - } _ => {} } } @@ -90,10 +114,7 @@ pub(crate) fn read(log: R, root: &str) -> Result, "build log has no `build-finished` message (truncated or failed build?)" )), Some(false) => Err(anyhow!("build log reports a failed build")), - Some(true) if !root_product => Err(anyhow!( - "build log has no product artifact for root package `{root}` (wrong -p, or `cargo check`?)" - )), - Some(true) => Ok(variants), + Some(true) => Ok(BuildLog { variants, products }), } } @@ -165,7 +186,7 @@ mod tests { } #[test] - fn reads_variants_including_fresh_and_skips_build_scripts() { + fn reads_variants_and_products_and_skips_build_scripts() { let text = log(&[ " Compiling serde v1.0.228".to_string(), artifact(SERDE, &["custom-build"], &["std"], "/t/build-script-build"), @@ -178,22 +199,37 @@ mod tests { key, features: features.iter().map(|f| f.to_string()).collect(), }; + let log = read(text.as_bytes()).unwrap(); let expected = BTreeSet::from([ variant(key("serde", "1.0.228"), &["std"]), variant(key("serde", "1.0.228"), &["derive", "std"]), variant(path_key("app", "1.0.0"), &["default"]), ]); - assert_eq!(read(text.as_bytes(), "app").unwrap(), expected); + assert_eq!(log.variants, expected); + assert!(log.products.contains(&path_key("app", "1.0.0"))); } #[test] fn requires_successful_final_build_finished() { let missing = log(&[root_artifact()]); - assert!(read(missing.as_bytes(), "app").is_err()); + assert!(read(missing.as_bytes()).is_err()); let failed = log(&[root_artifact(), finished(false)]); - assert!(read(failed.as_bytes(), "app").is_err()); + assert!(read(failed.as_bytes()).is_err()); let after = log(&[finished(true), root_artifact()]); - assert!(read(after.as_bytes(), "app").is_err()); + assert!(read(after.as_bytes()).is_err()); + let trailing_text = log(&[ + root_artifact(), + finished(true), + "{\"reason\":\"compiler-art".to_string(), + ]); + assert!(read(trailing_text.as_bytes()).is_err()); + let two_on_one_line = log(&[ + root_artifact(), + format!("{}{}", finished(true), finished(false)), + ]); + assert!(read(two_on_one_line.as_bytes()).is_err()); + let blank_after = log(&[root_artifact(), finished(true), String::new()]); + assert!(read(blank_after.as_bytes()).is_ok()); } #[test] @@ -203,7 +239,24 @@ mod tests { "{\"reason\":\"compiler-artifact\",\"truncated".to_string(), finished(true), ]); - assert!(read(text.as_bytes(), "app").is_err()); + assert!(read(text.as_bytes()).is_err()); + let incomplete = log(&[ + root_artifact(), + "{\"reason\":\"compiler-artifact\"}".to_string(), + finished(true), + ]); + assert!(read(incomplete.as_bytes()).is_err()); + } + + #[test] + fn ignores_other_message_kinds() { + let text = log(&[ + "{\"reason\":\"compiler-message\",\"anything\":1}".to_string(), + "{\"reason\":\"some-future-message\"}".to_string(), + root_artifact(), + finished(true), + ]); + assert!(read(text.as_bytes()).is_ok()); } #[test] @@ -215,23 +268,18 @@ mod tests { artifact(ROOT, &["bench"], &[], "/t/bench"), ] { let text = log(&[root_artifact(), bad, finished(true)]); - assert!(read(text.as_bytes(), "app").is_err()); + assert!(read(text.as_bytes()).is_err()); } } #[test] - fn requires_a_product_artifact_for_the_root() { - let check = log(&[ + fn only_linkable_outputs_are_products() { + let text = log(&[ artifact(ROOT, &["lib"], &[], "/t/libapp.rmeta"), + artifact(SERDE, &["lib"], &[], "/t/libserde.rlib"), finished(true), ]); - assert!(read(check.as_bytes(), "app").is_err()); - let wrong_root = log(&[root_artifact(), finished(true)]); - assert!(read(wrong_root.as_bytes(), "other").is_err()); - let plain_lib = log(&[ - artifact(ROOT, &["lib"], &[], "/t/libapp.rlib"), - finished(true), - ]); - assert!(read(plain_lib.as_bytes(), "app").is_ok()); + let log = read(text.as_bytes()).unwrap(); + assert_eq!(log.products, BTreeSet::from([key("serde", "1.0.228")])); } } diff --git a/allow-list/src/input/mod.rs b/allow-list/src/input/mod.rs index 7e8fa45..2d31d3a 100644 --- a/allow-list/src/input/mod.rs +++ b/allow-list/src/input/mod.rs @@ -1,8 +1,9 @@ //! Input readers: turn one target's raw build evidence into a [`TargetGraph`]. //! //! This is the only module that knows input formats. Today there is one reader, which combines -//! a cargo build log with two `cargo tree` outputs produced by the same invocation; see the -//! README for the producer recipe and for what the cross-checks below do and do not prove. +//! a cargo build log with two `cargo tree` outputs, run as separate commands with identical +//! arguments in the build's environment; see the README for the producer recipe and for what +//! the cross-checks below do and do not prove. mod build_log; mod cargo_tree; @@ -65,11 +66,11 @@ impl TargetInput { tree, runtime_tree, } => { - let compiled = build_log::read(BufReader::new(open(log)?), root) + let log = build_log::read(BufReader::new(open(log)?)) .with_context(|| format!("reading {}", log.display()))?; let tree = parse_tree(tree)?; let runtime = parse_tree(runtime_tree)?; - graph_from_log_and_tree(root, &compiled, tree, &runtime) + graph_from_log_and_tree(root, &log, tree, &runtime) } } } @@ -88,7 +89,7 @@ fn parse_tree(path: &Path) -> Result { /// Cross-check the build log against the trees, then assign roles from the runtime tree fn graph_from_log_and_tree( root: &str, - compiled: &BTreeSet, + log: &build_log::BuildLog, tree: cargo_tree::Tree, runtime: &cargo_tree::Tree, ) -> Result { @@ -98,6 +99,12 @@ fn graph_from_log_and_tree( tree.root.name )); } + if !log.products.contains(&tree.root) { + return Err(anyhow!( + "the build log has no product artifact for {} (wrong -p, or `cargo check`?)", + tree.root + )); + } if runtime.root != tree.root { return Err(anyhow!( "the runtime tree's root {} differs from the full tree's root {}", @@ -106,6 +113,7 @@ fn graph_from_log_and_tree( )); } + let compiled = &log.variants; let compiled_packages: BTreeSet<&PackageKey> = compiled.iter().map(|v| &v.key).collect(); let tree_packages = tree.packages(); check_same( @@ -175,3 +183,99 @@ impl std::fmt::Display for Variant { write!(f, "{} [{}]", self.key, features.join(",")) } } + +#[cfg(test)] +mod tests { + use super::build_log::BuildLog; + use super::*; + use crate::graph::test_util::{key, path_key}; + + const TREE: &str = "0app v1.0.0 (/build/app)|default\n1serde v1.0.0|std\n1cc v1.0.0|\n"; + const RUNTIME: &str = "0app v1.0.0 (/build/app)|default\n1serde v1.0.0|std\n"; + + fn variant(key: PackageKey, features: &[&str]) -> Variant { + Variant { + key, + features: features.iter().map(|f| f.to_string()).collect(), + } + } + + fn log() -> BuildLog { + BuildLog { + variants: BTreeSet::from([ + variant(path_key("app", "1.0.0"), &["default"]), + variant(key("serde", "1.0.0"), &["std"]), + variant(key("cc", "1.0.0"), &[]), + ]), + products: BTreeSet::from([path_key("app", "1.0.0")]), + } + } + + fn graph(log: &BuildLog, tree: &str, runtime: &str) -> Result { + let tree = cargo_tree::parse(tree).unwrap(); + let runtime = cargo_tree::parse(runtime).unwrap(); + graph_from_log_and_tree("app", log, tree, &runtime).map_err(|e| e.to_string()) + } + + #[test] + fn assigns_roles_from_the_runtime_tree() { + let graph = graph(&log(), TREE, RUNTIME).unwrap(); + assert_eq!(graph.packages()[&key("serde", "1.0.0")], Role::Runtime); + assert_eq!(graph.packages()[&key("cc", "1.0.0")], Role::BuildTime); + assert_eq!(graph.edges().len(), 2); + } + + #[test] + fn rejects_a_package_missing_from_either_side() { + let mut dropped = log(); + dropped.variants.remove(&variant(key("cc", "1.0.0"), &[])); + assert!(graph(&dropped, TREE, RUNTIME) + .unwrap_err() + .contains("cc@1.0.0")); + let mut extra = log(); + extra.variants.insert(variant(key("ring", "1.0.0"), &[])); + assert!(graph(&extra, TREE, RUNTIME) + .unwrap_err() + .contains("ring@1.0.0")); + } + + #[test] + fn rejects_a_variant_with_different_features() { + let mut other = log(); + other + .variants + .remove(&variant(key("serde", "1.0.0"), &["std"])); + other + .variants + .insert(variant(key("serde", "1.0.0"), &["std", "derive"])); + let err = graph(&other, TREE, RUNTIME).unwrap_err(); + assert!(err.contains("variants"), "{err}"); + } + + #[test] + fn rejects_a_runtime_tree_from_different_arguments() { + let runtime = "0app v1.0.0 (/build/app)|default\n1serde v1.0.0|std,alloc\n"; + let err = graph(&log(), TREE, runtime).unwrap_err(); + assert!(err.contains("runtime tree has variants missing"), "{err}"); + } + + #[test] + fn rejects_mismatched_roots() { + let runtime = "0other v1.0.0 (/build/other)|\n"; + assert!(graph(&log(), TREE, runtime).unwrap_err().contains("root")); + let tree = cargo_tree::parse(TREE).unwrap(); + let runtime = cargo_tree::parse(RUNTIME).unwrap(); + assert!(graph_from_log_and_tree("other", &log(), tree, &runtime).is_err()); + } + + #[test] + fn requires_a_product_artifact_for_the_root() { + let mut check = log(); + check.products.clear(); + // a dependency with the same name does not count + check.products.insert(key("app", "2.0.0")); + assert!(graph(&check, TREE, RUNTIME) + .unwrap_err() + .contains("no product artifact")); + } +} diff --git a/allow-list/src/inventory.rs b/allow-list/src/inventory.rs index ca66f0c..67d0892 100644 --- a/allow-list/src/inventory.rs +++ b/allow-list/src/inventory.rs @@ -70,6 +70,12 @@ pub(crate) fn build<'m>( let resolved = resolve(roles.keys().copied(), metadata)?; let root = resolved[root_key]; let workspace: BTreeSet<&PackageId> = metadata.workspace_members.iter().collect(); + // the root is never approved or license-checked, so it must be our own code + if !workspace.contains(&root.id) { + return Err(anyhow!( + "the root package {root_key} is not a workspace member" + )); + } let mut components: Vec = roles .iter() @@ -342,6 +348,14 @@ mod tests { assert!(!tool.first_party); } + #[test] + fn rejects_a_root_that_is_not_a_workspace_member() { + let root = key("x", "1.0.0"); + let meta = metadata(&[(root.clone(), Some("MIT"))]); + let err = build(&[graph(&root, &[], &[])], &meta, |_| false).unwrap_err(); + assert!(err.to_string().contains("not a workspace member"), "{err}"); + } + #[test] fn rejects_targets_with_different_roots() { let (a, b) = (path_key("a", "1.0.0"), path_key("b", "1.0.0")); diff --git a/allow-list/src/sbom.rs b/allow-list/src/sbom.rs index f3d3933..073ce2e 100644 --- a/allow-list/src/sbom.rs +++ b/allow-list/src/sbom.rs @@ -16,7 +16,7 @@ use cyclonedx_bom::models::license::{License, LicenseChoice, Licenses}; use cyclonedx_bom::models::tool::Tools; use cyclonedx_bom::prelude::*; use serde::Deserialize; -use std::collections::{BTreeMap, HashMap}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::io::Write; /// SHA-256 checksums of crates.io packages, from a `Cargo.lock` @@ -38,14 +38,24 @@ impl Checksums { checksum: Option, } let lockfile: Lockfile = toml::from_str(text)?; - Ok(Self( - lockfile - .package - .into_iter() - .filter(|p| p.source.as_deref().is_some_and(is_crates_io)) - .filter_map(|p| Some(((p.name, p.version), p.checksum?))) - .collect(), - )) + let mut checksums = HashMap::new(); + for package in lockfile.package { + if !package.source.as_deref().is_some_and(is_crates_io) { + continue; + } + let Some(checksum) = package.checksum else { + continue; + }; + if checksum.len() != 64 || !checksum.bytes().all(|b| b.is_ascii_hexdigit()) { + return Err(anyhow!( + "invalid SHA-256 checksum for {} {} in the lockfile: {checksum:?}", + package.name, + package.version + )); + } + checksums.insert((package.name, package.version), checksum); + } + Ok(Self(checksums)) } fn get(&self, package: &Package) -> Option<&String> { @@ -84,22 +94,37 @@ pub(crate) fn write( let root = validated.root; let packages = std::iter::once(root).chain(validated.components.iter().map(|a| a.component.package)); + let mut purls: HashMap<&PackageId, Purl> = HashMap::new(); let mut refs: HashMap<&PackageId, String> = HashMap::new(); + let mut unique = HashSet::new(); for package in packages { - let purl = purl(package)?.to_string(); - if refs.values().any(|r| *r == purl) { - return Err(anyhow!("two packages share the reference {purl}")); + let purl = Purl::new("cargo", &package.name, &package.version.to_string())?; + let bom_ref = purl.to_string(); + if !unique.insert(bom_ref.clone()) { + return Err(anyhow!("two packages share the reference {bom_ref}")); } - refs.insert(&package.id, purl); + purls.insert(&package.id, purl); + refs.insert(&package.id, bom_ref); } + // a library component referenced by its purl + let component = |package: &Package| { + let mut component = Component::new( + Classification::Library, + &package.name, + &package.version.to_string(), + Some(refs[&package.id].clone()), + ); + component.purl = Some(purls[&package.id].clone()); + component + }; - let mut root_component = component(root)?; + let mut root_component = component(root); root_component.licenses = Some(commercial()); let mut components = Vec::new(); for approved in &validated.components { let package = approved.component.package; - let mut component = component(package)?; + let mut component = component(package); component.scope = Some(match approved.component.role { Role::Runtime => Scope::Required, Role::BuildTime => Scope::Excluded, @@ -203,23 +228,176 @@ pub(crate) fn write( Ok(()) } -fn purl(package: &Package) -> Result { - Ok(Purl::new( - "cargo", - &package.name, - &package.version.to_string(), - )?) -} +#[cfg(test)] +mod tests { + use super::*; + use crate::approval; + use crate::config::Config; + use crate::graph::test_util::{key, path_key}; + use crate::graph::{PackageKey, TargetGraph}; + use crate::inventory::{self, test_util::metadata}; + use std::collections::{BTreeMap, BTreeSet}; -/// A library component referenced by its purl -fn component(package: &Package) -> Result { - let purl = purl(package)?; - let mut component = Component::new( - Classification::Library, - &package.name, - &package.version.to_string(), - Some(purl.to_string()), - ); - component.purl = Some(purl); - Ok(component) + const HASH_A: &str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + const HASH_B: &str = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; + + fn config() -> Config { + serde_json::from_value(serde_json::json!({ + "build_only": ["cc"], + "vendor": {"sfio": {"url": "https://example.com/sfio"}}, + "third_party": {"serde": {"id": "serde", "source": "crates.io", "licenses": [{"MIT": {"copyright": "NotPresent"}}]}}, + "commercial_license": {"name": "Commercial", "url": "https://example.com/license"} + })) + .unwrap() + } + + fn lockfile(entries: &[(&str, &str, &str)]) -> String { + entries + .iter() + .map(|(name, version, checksum)| { + format!("[[package]]\nname = \"{name}\"\nversion = \"{version}\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"{checksum}\"\n") + }) + .collect() + } + + /// Render the SBOM of `app` with the given dependencies, all directly under the root + fn render( + deps: &[(PackageKey, Option<&str>, Role)], + checksums: Option<&Checksums>, + ) -> Result { + let app = path_key("app", "1.0.0"); + let mut packages: Vec<(PackageKey, Option<&str>)> = + deps.iter().map(|(k, l, _)| (k.clone(), *l)).collect(); + packages.push((app.clone(), None)); + let meta = metadata(&packages); + let mut members: BTreeMap = + deps.iter().map(|(k, _, r)| (k.clone(), *r)).collect(); + members.insert(app.clone(), Role::Runtime); + let edges: BTreeSet<_> = deps + .iter() + .map(|(k, _, _)| (app.clone(), k.clone())) + .collect(); + let graph = TargetGraph::new(app, members, edges)?; + let inventory = inventory::build(&[graph], &meta, |_| false)?; + let config = config(); + let validated = approval::validate(inventory, &config)?; + let options = Options { + checksums, + omit_serial_number: true, + timestamp: DateTime::try_from("2025-01-01T00:00:00Z".to_string()).unwrap(), + }; + let mut out = Vec::new(); + write( + &validated, + config.commercial_license.as_ref(), + &options, + &mut out, + )?; + Ok(serde_json::from_slice(&out)?) + } + + fn component<'a>( + bom: &'a serde_json::Value, + name: &str, + version: &str, + ) -> &'a serde_json::Value { + bom["components"] + .as_array() + .unwrap() + .iter() + .find(|c| c["name"] == name && c["version"] == version) + .unwrap() + } + + #[test] + fn encodes_scope_license_and_references_per_approval() { + let bom = render( + &[ + (key("serde", "1.0.0"), Some("MIT/Apache-2.0"), Role::Runtime), + (key("cc", "1.0.0"), None, Role::BuildTime), + (key("sfio", "1.0.0"), None, Role::Runtime), + ], + None, + ) + .unwrap(); + let serde = component(&bom, "serde", "1.0.0"); + assert_eq!(serde["scope"], "required"); + assert_eq!(serde["bom-ref"], "pkg:cargo/serde@1.0.0"); + assert_eq!(serde["licenses"][0]["expression"], "MIT OR Apache-2.0"); + let cc = component(&bom, "cc", "1.0.0"); + assert_eq!(cc["scope"], "excluded"); + assert!(cc.get("licenses").is_none()); + let sfio = component(&bom, "sfio", "1.0.0"); + assert_eq!(sfio["licenses"][0]["license"]["name"], "Commercial"); + assert_eq!( + sfio["licenses"][0]["license"]["url"], + "https://example.com/license" + ); + assert_eq!( + sfio["externalReferences"][0]["url"], + "https://example.com/sfio" + ); + assert_eq!( + bom["metadata"]["component"]["licenses"][0]["license"]["name"], + "Commercial" + ); + let root_deps = bom["dependencies"] + .as_array() + .unwrap() + .iter() + .find(|d| d["ref"] == "pkg:cargo/app@1.0.0") + .unwrap(); + assert_eq!(root_deps["dependsOn"].as_array().unwrap().len(), 3); + } + + #[test] + fn hashes_each_version_from_its_own_lockfile_entry() { + let checksums = Checksums::from_lockfile(&lockfile(&[ + ("serde", "1.0.0", HASH_A), + ("serde", "2.0.0", HASH_B), + ])) + .unwrap(); + let bom = render( + &[ + (key("serde", "1.0.0"), Some("MIT"), Role::Runtime), + (key("serde", "2.0.0"), Some("MIT"), Role::Runtime), + ], + Some(&checksums), + ) + .unwrap(); + assert_eq!( + component(&bom, "serde", "1.0.0")["hashes"][0]["content"], + HASH_A + ); + assert_eq!( + component(&bom, "serde", "2.0.0")["hashes"][0]["content"], + HASH_B + ); + } + + #[test] + fn rejects_invalid_checksums() { + for bad in [ + "0000", + "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", + ] { + assert!(Checksums::from_lockfile(&lockfile(&[("serde", "1.0.0", bad)])).is_err()); + } + let trailing = format!("{HASH_A}NOTHEX"); + assert!(Checksums::from_lockfile(&lockfile(&[("serde", "1.0.0", &trailing)])).is_err()); + } + + #[test] + fn rejects_colliding_references() { + // a workspace member and a crates.io package with the same name and version + let err = render( + &[ + (path_key("serde", "1.0.0"), None, Role::Runtime), + (key("serde", "1.0.0"), Some("MIT"), Role::Runtime), + ], + None, + ) + .unwrap_err(); + assert!(err.to_string().contains("share the reference"), "{err}"); + } } diff --git a/allow-list/tests/fixtures/workspace/Cargo.lock b/allow-list/tests/fixtures/workspace/Cargo.lock index 6e29901..36267b2 100644 --- a/allow-list/tests/fixtures/workspace/Cargo.lock +++ b/allow-list/tests/fixtures/workspace/Cargo.lock @@ -24,6 +24,10 @@ dependencies = [ name = "common" version = "0.1.0" +[[package]] +name = "hostextra" +version = "0.1.0" + [[package]] name = "optdep" version = "0.1.0" @@ -43,6 +47,9 @@ version = "0.1.0" [[package]] name = "shared" version = "0.1.0" +dependencies = [ + "hostextra", +] [[package]] name = "tool" diff --git a/allow-list/tests/fixtures/workspace/Cargo.toml b/allow-list/tests/fixtures/workspace/Cargo.toml index 35365af..175ac8f 100644 --- a/allow-list/tests/fixtures/workspace/Cargo.toml +++ b/allow-list/tests/fixtures/workspace/Cargo.toml @@ -2,4 +2,4 @@ # built for real by the tests in `allow-list/src/fixture_tests.rs`. [workspace] resolver = "2" -members = ["app", "shared", "common", "pm", "pmonly", "tool", "alias-target", "optdep", "winonly", "unixonly"] +members = ["app", "shared", "hostextra", "common", "pm", "pmonly", "tool", "alias-target", "optdep", "winonly", "unixonly"] diff --git a/allow-list/tests/fixtures/workspace/hostextra/Cargo.toml b/allow-list/tests/fixtures/workspace/hostextra/Cargo.toml new file mode 100644 index 0000000..db8164c --- /dev/null +++ b/allow-list/tests/fixtures/workspace/hostextra/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "hostextra" +version = "0.1.0" +edition = "2021" +publish = false diff --git a/allow-list/tests/fixtures/workspace/hostextra/src/lib.rs b/allow-list/tests/fixtures/workspace/hostextra/src/lib.rs new file mode 100644 index 0000000..d2c288c --- /dev/null +++ b/allow-list/tests/fixtures/workspace/hostextra/src/lib.rs @@ -0,0 +1 @@ +pub fn hostextra() {} diff --git a/allow-list/tests/fixtures/workspace/shared/Cargo.toml b/allow-list/tests/fixtures/workspace/shared/Cargo.toml index af8e71d..68cf7e3 100644 --- a/allow-list/tests/fixtures/workspace/shared/Cargo.toml +++ b/allow-list/tests/fixtures/workspace/shared/Cargo.toml @@ -4,6 +4,10 @@ version = "0.1.0" edition = "2021" publish = false +[dependencies] +# only enabled by `host-feat`, which only the proc-macro (host) side requests +hostextra = { path = "../hostextra", optional = true } + [features] target-feat = [] -host-feat = [] +host-feat = ["dep:hostextra"] From 6b60e264db2abfde1878a2eb4ab5f9b657ec8347 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 12:56:22 -0700 Subject: [PATCH 04/12] Reject duplicate keys in build log messages; README scope fixes - deserialize each cargo message from the original line rather than an intermediate serde_json::Value, which kept the last of duplicate keys - fixture build evidence lives in a fixed, cleared directory inside the target directory instead of accumulating in the system temp dir - README: state exactly what the cross-checks prove, scope the approval rules to the build-evidence commands and non-workspace packages, and document the workspace-root and commercial_license requirements --- README.md | 18 +++++++++------ allow-list/src/fixture_tests.rs | 13 ++++++----- allow-list/src/golden_tests.rs | 6 ++++- allow-list/src/input/build_log.rs | 38 +++++++++++++++++++++++++------ 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 9d72e11..6f0f8bc 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,8 @@ dependency graph could contain. For each target the product is built for: 2. `cargo tree` (Cargo's own resolver) tells which of them are linked into the product (**runtime**) and which only run while building it (**build time**: build scripts, proc-macros and their dependencies); -3. the two are cross-checked, so evidence from a different invocation fails loudly. +3. the two are cross-checked: if they disagree on the compiled packages or their enabled + features (for example a tree made with different flags), the run fails. Targets are merged (a package that is runtime on any target is runtime), resolved against `cargo metadata` for licenses and sources, and approved against `allowed.json`. The license @@ -98,18 +99,20 @@ features the product was built with. } ``` -Rules, checked on every run (all violations are reported together): +Rules, checked by the build-evidence commands (`gen-licenses-log*`, `gen-sbom-log*`; all +violations are reported together). Workspace members are our own code and need no entry; the +root package must be one. - every compiled package outside the workspace is in **exactly one** list; -- a runtime package must be in `third_party` or `vendor`; a `build_only` package that becomes - linked into the product is an error; +- a runtime package outside the workspace must be in `third_party` or `vendor`; a `build_only` + package that becomes linked into the product is an error; - a build-time package may be in any list; - only crates.io and workspace packages are supported; - for runtime `third_party` packages, every reviewed license must be part of the package's declared SPDX `license`, and the reviewed licenses must satisfy it (reviewed `MIT` satisfies `MIT OR Apache-2.0` but not `MIT AND Apache-2.0`). -`embedded: true` marks a build-time dependency whose own code ships anyway (for example a build +`commercial_license` is required by the SBOM commands. `embedded: true` marks a build-time dependency whose own code ships anyway (for example a build script that copies source it provides into the product); it is treated as runtime, its dependencies are not. License names: `MIT`, `ISC`, `BSD3` (with `copyright`), `Apache2`, `OpenSSL`, `BSLv1`, `MPLv2`, `UnicodeDFS2016`. @@ -117,8 +120,9 @@ dependencies are not. License names: `MIT`, `ISC`, `BSD3` (with `copyright`), `A ## Guarantees and limits The cross-checks prove that the full `cargo tree` has exactly the packages, and exactly the -(package, enabled features) variants, of the build log, and that the runtime tree is part of -the full tree. That catches different feature flags, wider builds and dropped artifacts whose +(package, enabled features) variants, of the build log, and that every variant in the runtime +tree is also in the full tree. They do not prove that the files came from one invocation, nor +anything about edges. That catches different feature flags, wider builds and dropped artifacts whose features differ from the package's other variants. Not detected, so guaranteed only by producing the files as above: diff --git a/allow-list/src/fixture_tests.rs b/allow-list/src/fixture_tests.rs index 34bcf47..aa273e5 100644 --- a/allow-list/src/fixture_tests.rs +++ b/allow-list/src/fixture_tests.rs @@ -24,13 +24,14 @@ fn evidence() -> &'static Evidence { static EVIDENCE: OnceLock = OnceLock::new(); EVIDENCE.get_or_init(|| { let workspace = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/workspace"); - let nanos = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) + // a fixed directory next to the test binary (inside cargo's target directory, so it is + // bounded and removed by `cargo clean`), emptied first so every artifact is built by + // this run + let dir = std::env::current_exe() .unwrap() - .as_nanos(); - let dir = - std::env::temp_dir().join(format!("allow-list-fixture-{}-{nanos}", std::process::id())); - // start from an empty target directory, so every artifact is built by this run + .parent() + .unwrap() + .join("allow-list-fixture-evidence"); let _ = std::fs::remove_dir_all(&dir); std::fs::create_dir_all(&dir).unwrap(); let host = host_triple(); diff --git a/allow-list/src/golden_tests.rs b/allow-list/src/golden_tests.rs index 0711215..6d74a51 100644 --- a/allow-list/src/golden_tests.rs +++ b/allow-list/src/golden_tests.rs @@ -443,7 +443,11 @@ fn sbom_needs_a_commercial_license_and_lockfile_checksums() { let mut evidence = all_targets(); let mut config: serde_json::Value = load("allowed.json"); config.as_object_mut().unwrap().remove("commercial_license"); - let dir = std::env::temp_dir().join(format!("allow-list-golden-{}", std::process::id())); + let dir = std::env::current_exe() + .unwrap() + .parent() + .unwrap() + .join("allow-list-golden-config"); std::fs::create_dir_all(&dir).unwrap(); evidence.config = dir.join("allowed.json"); std::fs::write(&evidence.config, config.to_string()).unwrap(); diff --git a/allow-list/src/input/build_log.rs b/allow-list/src/input/build_log.rs index 9091317..32054ec 100644 --- a/allow-list/src/input/build_log.rs +++ b/allow-list/src/input/build_log.rs @@ -21,6 +21,12 @@ const PRODUCT_KINDS: [TargetKind; 6] = [ const NON_PRODUCT_KINDS: [TargetKind; 3] = [TargetKind::Example, TargetKind::Test, TargetKind::Bench]; +/// Just the kind of a cargo JSON message +#[derive(serde::Deserialize)] +struct MessageKind { + reason: Option, +} + /// What a build log proves #[derive(Debug)] pub(crate) struct BuildLog { @@ -55,18 +61,21 @@ pub(crate) fn read(log: R) -> Result { if !line.starts_with('{') { continue; } - // parse the whole line, so that a truncated or concatenated message is an error - let value: serde_json::Value = serde_json::from_str(line) - .map_err(|err| anyhow!("build log line {line_number}: malformed message: {err}"))?; - // compiler diagnostics, build script output and future message kinds carry no scope + // Deserialize the original line (never an intermediate `Value`, which would silently + // keep the last of duplicate keys), so a truncated, concatenated or ambiguous message + // is an error. Other message kinds (diagnostics, build script output, future kinds) + // carry no scope and are skipped. + let malformed = |err: serde_json::Error| { + anyhow!("build log line {line_number}: malformed message: {err}") + }; + let kind: MessageKind = serde_json::from_str(line).map_err(malformed)?; if !matches!( - value["reason"].as_str(), + kind.reason.as_deref(), Some("compiler-artifact" | "build-finished") ) { continue; } - let message = serde_json::from_value(value) - .map_err(|err| anyhow!("build log line {line_number}: malformed message: {err}"))?; + let message: Message = serde_json::from_str(line).map_err(malformed)?; match message { Message::CompilerArtifact(artifact) => { if artifact.profile.test @@ -228,6 +237,21 @@ mod tests { format!("{}{}", finished(true), finished(false)), ]); assert!(read(two_on_one_line.as_bytes()).is_err()); + let ambiguous = log(&[ + root_artifact(), + "{\"reason\":\"build-finished\",\"success\":false,\"success\":true}".to_string(), + ]); + assert!(read(ambiguous.as_bytes()).is_err()); + let duplicate_reason = log(&[ + root_artifact(), + "{\"reason\":\"compiler-message\",\"reason\":\"build-finished\",\"success\":true}" + .to_string(), + ]); + assert!(read(duplicate_reason.as_bytes()).is_err()); + let duplicate_features = + root_artifact().replacen("\"features\":", "\"features\":[],\"features\":", 1); + let text = log(&[duplicate_features, finished(true)]); + assert!(read(text.as_bytes()).is_err()); let blank_after = log(&[root_artifact(), finished(true), String::new()]); assert!(read(blank_after.as_bytes()).is_ok()); } From a9e684883b79b895473c071947dc1cfd293878e6 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 12:58:13 -0700 Subject: [PATCH 05/12] Isolate test scratch directories per process Concurrent test runs must not share the fixture build or the golden test's temporary config; keep them per process inside the target directory. --- allow-list/src/fixture_tests.rs | 11 +++++++---- allow-list/src/golden_tests.rs | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/allow-list/src/fixture_tests.rs b/allow-list/src/fixture_tests.rs index aa273e5..4352569 100644 --- a/allow-list/src/fixture_tests.rs +++ b/allow-list/src/fixture_tests.rs @@ -24,14 +24,17 @@ fn evidence() -> &'static Evidence { static EVIDENCE: OnceLock = OnceLock::new(); EVIDENCE.get_or_init(|| { let workspace = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/workspace"); - // a fixed directory next to the test binary (inside cargo's target directory, so it is - // bounded and removed by `cargo clean`), emptied first so every artifact is built by - // this run + // a per-process directory next to the test binary: isolated from concurrent test runs, + // inside cargo's target directory (removed by `cargo clean`), and emptied first so + // every artifact is built by this run let dir = std::env::current_exe() .unwrap() .parent() .unwrap() - .join("allow-list-fixture-evidence"); + .join(format!( + "allow-list-fixture-evidence-{}", + std::process::id() + )); let _ = std::fs::remove_dir_all(&dir); std::fs::create_dir_all(&dir).unwrap(); let host = host_triple(); diff --git a/allow-list/src/golden_tests.rs b/allow-list/src/golden_tests.rs index 6d74a51..e3b56c3 100644 --- a/allow-list/src/golden_tests.rs +++ b/allow-list/src/golden_tests.rs @@ -447,7 +447,7 @@ fn sbom_needs_a_commercial_license_and_lockfile_checksums() { .unwrap() .parent() .unwrap() - .join("allow-list-golden-config"); + .join(format!("allow-list-golden-config-{}", std::process::id())); std::fs::create_dir_all(&dir).unwrap(); evidence.config = dir.join("allowed.json"); std::fs::write(&evidence.config, config.to_string()).unwrap(); From d8dadfb01673cbacf8c1ff52053ed8682f1b75f3 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 14:01:32 -0700 Subject: [PATCH 06/12] Prune redundant tests and repair ineffective ones Agreed with Codex review: - cut tests duplicated elsewhere (Role ordering, path-key resolution, the executable-documentation limitation test, standalone 1.5 validation now folded into the SBOM content test as a parse-back check) - the missing commercial license is a renderer unit test; the command test proves --lockfile reaches the renderer without temp files - repaired tests that passed with a wrong implementation: build-script skip (distinct features), blank lines after build-finished, runtime-wins in both target orders, and an independent expected set for the license report (precursor-derived) - one graph test helper and one Variant constructor instead of copies --- allow-list/src/approval.rs | 34 +++--------- allow-list/src/fixture_tests.rs | 19 +------ allow-list/src/golden_tests.rs | 88 +++++++++++++----------------- allow-list/src/graph.rs | 21 +++++-- allow-list/src/input/build_log.rs | 26 ++++++--- allow-list/src/input/cargo_tree.rs | 15 ++--- allow-list/src/input/mod.rs | 35 +++++++----- allow-list/src/inventory.rs | 46 ++++++++++------ allow-list/src/sbom.rs | 39 +++++++------ 9 files changed, 156 insertions(+), 167 deletions(-) diff --git a/allow-list/src/approval.rs b/allow-list/src/approval.rs index 9620fba..f9f1150 100644 --- a/allow-list/src/approval.rs +++ b/allow-list/src/approval.rs @@ -216,10 +216,9 @@ fn check_reviewed_license( #[cfg(test)] mod tests { use super::*; - use crate::graph::test_util::{key, path_key}; - use crate::graph::{PackageKey, TargetGraph}; - use crate::inventory::test_util::metadata; - use cargo_metadata::Metadata; + use crate::graph::test_util::key; + use crate::graph::PackageKey; + use crate::inventory::test_util::app_with; fn config(json: serde_json::Value) -> Config { serde_json::from_value(json).unwrap() @@ -231,19 +230,11 @@ mod tests { /// Inventory of an `app` with the given (name, declared license, role) dependencies fn check(deps: &[(&str, Option<&str>, Role)], config: &Config) -> Result<(), String> { - let app = path_key("app", "1.0.0"); - let keys: Vec<(PackageKey, Option<&str>, Role)> = deps + let deps: Vec<(PackageKey, Option<&str>, Role)> = deps .iter() .map(|(name, license, role)| (key(name, "1.0.0"), *license, *role)) .collect(); - let mut packages: Vec<(PackageKey, Option<&str>)> = - keys.iter().map(|(k, l, _)| (k.clone(), *l)).collect(); - packages.push((app.clone(), None)); - let meta: Metadata = metadata(&packages); - let mut members: BTreeMap = - keys.iter().map(|(k, _, r)| (k.clone(), *r)).collect(); - members.insert(app.clone(), Role::Runtime); - let graph = TargetGraph::new(app, members, BTreeSet::new()).unwrap(); + let (meta, graph) = app_with(&deps); let inventory = crate::inventory::build(&[graph], &meta, |_| false).unwrap(); validate(inventory, config) .map(|_| ()) @@ -370,19 +361,10 @@ mod tests { #[test] fn license_report_lists_only_shipped_third_party_packages() { - let app = path_key("app", "1.0.0"); - let (serde, regex) = (key("serde", "1.0.0"), key("regex", "1.0.0")); - let meta = metadata(&[ - (app.clone(), None), - (serde.clone(), Some("MIT")), - (regex.clone(), Some("MIT")), + let (meta, graph) = app_with(&[ + (key("serde", "1.0.0"), Some("MIT"), Role::Runtime), + (key("regex", "1.0.0"), Some("MIT"), Role::BuildTime), ]); - let members = BTreeMap::from([ - (app.clone(), Role::Runtime), - (serde, Role::Runtime), - (regex, Role::BuildTime), - ]); - let graph = TargetGraph::new(app, members, BTreeSet::new()).unwrap(); let inventory = crate::inventory::build(&[graph], &meta, |_| false).unwrap(); let mut json = empty(); json["third_party"]["serde"] = mit("serde"); diff --git a/allow-list/src/fixture_tests.rs b/allow-list/src/fixture_tests.rs index 4352569..ef6eb04 100644 --- a/allow-list/src/fixture_tests.rs +++ b/allow-list/src/fixture_tests.rs @@ -5,7 +5,7 @@ //! artifact features) and fail when a new Cargo release changes it. use crate::config::Config; -use crate::graph::{PackageKey, Role, TargetGraph}; +use crate::graph::{Role, TargetGraph}; use crate::input::TargetInput; use crate::{approval, inventory}; use cargo_metadata::Metadata; @@ -249,14 +249,6 @@ fn a_dropped_artifact_with_distinct_features_is_detected() { ); } -#[test] -fn a_dropped_artifact_with_identical_features_is_not_detected() { - // Documented limit: `common` compiles twice (host and target) with identical features, so - // the variant sets cannot tell that one of the artifacts is missing. - let log = log_without("common", |_| true); - assert!(input(&log).read("app").is_ok()); -} - #[test] fn the_core_needs_no_approval_for_workspace_members() { let graph = read(); @@ -267,12 +259,3 @@ fn the_core_needs_no_approval_for_workspace_members() { let validated = approval::validate(inventory, &config).unwrap(); assert!(validated.shipped_third_party().is_empty()); } - -#[test] -fn keys_resolve_to_workspace_members() { - let graph = read(); - let keys: Vec<&PackageKey> = graph.packages().keys().collect(); - assert!(keys - .iter() - .all(|k| k.source == crate::graph::SourceKind::Path)); -} diff --git a/allow-list/src/golden_tests.rs b/allow-list/src/golden_tests.rs index e3b56c3..ca93cb4 100644 --- a/allow-list/src/golden_tests.rs +++ b/allow-list/src/golden_tests.rs @@ -270,25 +270,11 @@ fn unapproved_or_misreviewed_dependencies_are_all_reported() { } } -#[test] -fn license_report_lists_exactly_the_shipped_third_party_crates() { +/// The (crate, version) pairs listed by the license report of `evidence` +fn reported(evidence: &Evidence) -> BTreeSet<(String, String)> { let mut out = Vec::new(); - commands::gen_licenses(&all_targets(), &mut out).unwrap(); + commands::gen_licenses(evidence, &mut out).unwrap(); let report = String::from_utf8(out).unwrap(); - let crates: BTreeSet<&str> = report - .lines() - .filter_map(|l| l.strip_prefix("crate: ")) - .collect(); - assert!( - crates.contains("ring") && crates.contains("aws-lc-sys") && crates.contains("oo-bindgen") - ); - for build_time in ["syn", "serde_derive", "regex", "cc", "tokio-macros"] { - assert!(!crates.contains(build_time), "{build_time}"); - } - for not_third_party in ["dnp3", "sfio-promise", "sfio-tokio-ffi"] { - assert!(!crates.contains(not_third_party), "{not_third_party}"); - } - // the report and the SBOM are projections of the same inventory, down to every version let mut reported = BTreeSet::new(); let mut lines = report.lines(); while let Some(line) = lines.next() { @@ -299,7 +285,29 @@ fn license_report_lists_exactly_the_shipped_third_party_crates() { } } } - assert_eq!(reported, sbom_required_third_party(&sbom_document())); + reported +} + +#[test] +fn license_report_lists_exactly_the_shipped_third_party_crates() { + // independent expectation: the precursor-derived runtime set, minus first-party and vendor + // packages, plus the embedded third-party build dependency + let mut expected: BTreeSet<&str> = BTreeSet::from(RUNTIME); + for not_third_party in ["dnp3", "dnp3-ffi", "sfio-promise"] { + expected.remove(not_third_party); + } + expected.insert("oo-bindgen"); + let reported = reported(&one_target("aws")); + let names: BTreeSet<&str> = reported.iter().map(|(name, _)| name.as_str()).collect(); + assert_eq!(names, expected); +} + +#[test] +fn license_report_and_sbom_agree_on_every_shipped_version() { + assert_eq!( + reported(&all_targets()), + sbom_required_third_party(&sbom_document()) + ); } /// The SBOM of all targets, with a fixed timestamp and no serial number @@ -348,15 +356,14 @@ fn sbom_required_third_party(bom: &serde_json::Value) -> BTreeSet<(String, Strin } #[test] -fn sbom_is_valid_cyclonedx_1_5() { - let bom = Bom::parse_from_json_v1_5(sbom_bytes().as_slice()).unwrap(); - let validation = bom.validate_version(SpecVersion::V1_5); +fn sbom_scopes_licenses_hashes_and_edges() { + // the final bytes (after post-processing) must still parse and validate as CycloneDX 1.5 + let bytes = sbom_bytes(); + let parsed = Bom::parse_from_json_v1_5(bytes.as_slice()).unwrap(); + let validation = parsed.validate_version(SpecVersion::V1_5); assert!(validation.passed(), "{validation:?}"); -} -#[test] -fn sbom_scopes_licenses_hashes_and_edges() { - let bom = sbom_document(); + let bom: serde_json::Value = serde_json::from_slice(&bytes).unwrap(); let components = bom["components"].as_array().unwrap(); let component = |name: &str| components.iter().find(|c| c["name"] == name).unwrap(); @@ -438,32 +445,15 @@ fn sbom_is_reproducible() { } #[test] -fn sbom_needs_a_commercial_license_and_lockfile_checksums() { - let mut out = Vec::new(); - let mut evidence = all_targets(); - let mut config: serde_json::Value = load("allowed.json"); - config.as_object_mut().unwrap().remove("commercial_license"); - let dir = std::env::current_exe() - .unwrap() - .parent() - .unwrap() - .join(format!("allow-list-golden-config-{}", std::process::id())); - std::fs::create_dir_all(&dir).unwrap(); - evidence.config = dir.join("allowed.json"); - std::fs::write(&evidence.config, config.to_string()).unwrap(); - let options = SbomOptions { - lockfile: None, - omit_serial_number: false, - }; - let err = commands::gen_sbom(&evidence, &options, &mut out).unwrap_err(); - assert!(err.to_string().contains("commercial_license"), "{err}"); - - let lock = dir.join("Cargo.lock"); - std::fs::write(&lock, "version = 4\n").unwrap(); +fn sbom_command_uses_the_given_lockfile() { + // a lockfile without crates.io checksums (the path-only fixture workspace's) must be + // rejected, which proves the command passes `--lockfile` through to the renderer let options = SbomOptions { - lockfile: Some(lock), + lockfile: Some( + Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/workspace/Cargo.lock"), + ), omit_serial_number: false, }; - let err = commands::gen_sbom(&all_targets(), &options, &mut out).unwrap_err(); + let err = commands::gen_sbom(&all_targets(), &options, &mut Vec::new()).unwrap_err(); assert!(err.to_string().contains("no checksum"), "{err}"); } diff --git a/allow-list/src/graph.rs b/allow-list/src/graph.rs index 0dd3d9d..dc69573 100644 --- a/allow-list/src/graph.rs +++ b/allow-list/src/graph.rs @@ -129,6 +129,22 @@ pub(crate) mod test_util { ..key(name, version) } } + + /// A graph of `root` (always runtime) and the given packages and edges, for tests + pub(crate) fn graph( + root: &PackageKey, + packages: &[(&PackageKey, Role)], + edges: &[(&PackageKey, &PackageKey)], + ) -> TargetGraph { + let mut members: BTreeMap = + packages.iter().map(|(k, r)| ((*k).clone(), *r)).collect(); + members.insert(root.clone(), Role::Runtime); + let edges = edges + .iter() + .map(|(a, b)| ((*a).clone(), (*b).clone())) + .collect(); + TargetGraph::new(root.clone(), members, edges).unwrap() + } } #[cfg(test)] @@ -158,9 +174,4 @@ mod tests { let graph = TargetGraph::new(root, packages, edges).unwrap(); assert!(graph.edges().is_empty()); } - - #[test] - fn runtime_wins_when_merging_roles() { - assert_eq!(Role::BuildTime.max(Role::Runtime), Role::Runtime); - } } diff --git a/allow-list/src/input/build_log.rs b/allow-list/src/input/build_log.rs index 32054ec..b788f3a 100644 --- a/allow-list/src/input/build_log.rs +++ b/allow-list/src/input/build_log.rs @@ -198,21 +198,23 @@ mod tests { fn reads_variants_and_products_and_skips_build_scripts() { let text = log(&[ " Compiling serde v1.0.228".to_string(), - artifact(SERDE, &["custom-build"], &["std"], "/t/build-script-build"), + // distinct features, so the variant set changes if build scripts are not skipped + artifact( + SERDE, + &["custom-build"], + &["script"], + "/t/build-script-build", + ), artifact(SERDE, &["lib"], &["std"], "/t/libserde.rlib"), artifact(SERDE, &["lib"], &["derive", "std"], "/t/libserde-host.rlib"), root_artifact(), finished(true), ]); - let variant = |key, features: &[&str]| Variant { - key, - features: features.iter().map(|f| f.to_string()).collect(), - }; let log = read(text.as_bytes()).unwrap(); let expected = BTreeSet::from([ - variant(key("serde", "1.0.228"), &["std"]), - variant(key("serde", "1.0.228"), &["derive", "std"]), - variant(path_key("app", "1.0.0"), &["default"]), + Variant::new(key("serde", "1.0.228"), &["std"]), + Variant::new(key("serde", "1.0.228"), &["derive", "std"]), + Variant::new(path_key("app", "1.0.0"), &["default"]), ]); assert_eq!(log.variants, expected); assert!(log.products.contains(&path_key("app", "1.0.0"))); @@ -252,7 +254,13 @@ mod tests { root_artifact().replacen("\"features\":", "\"features\":[],\"features\":", 1); let text = log(&[duplicate_features, finished(true)]); assert!(read(text.as_bytes()).is_err()); - let blank_after = log(&[root_artifact(), finished(true), String::new()]); + // blank lines (empty or whitespace) after the end are allowed + let blank_after = log(&[ + root_artifact(), + finished(true), + String::new(), + " ".to_string(), + ]); assert!(read(blank_after.as_bytes()).is_ok()); } diff --git a/allow-list/src/input/cargo_tree.rs b/allow-list/src/input/cargo_tree.rs index a4c4995..b10cdef 100644 --- a/allow-list/src/input/cargo_tree.rs +++ b/allow-list/src/input/cargo_tree.rs @@ -140,13 +140,6 @@ mod tests { use super::*; use crate::graph::test_util::{key, path_key}; - fn variant(key: PackageKey, features: &[&str]) -> Variant { - Variant { - key, - features: features.iter().map(|f| f.to_string()).collect(), - } - } - #[test] fn parses_every_line_form() { let tree = parse(concat!( @@ -162,13 +155,13 @@ mod tests { assert_eq!(tree.root, path_key("app", "1.0.0")); assert!(tree .variants - .contains(&variant(path_key("app", "1.0.0"), &["default", "std"]))); + .contains(&Variant::new(path_key("app", "1.0.0"), &["default", "std"]))); assert!(tree .variants - .contains(&variant(key("serde_derive", "1.0.228"), &["default"]))); + .contains(&Variant::new(key("serde_derive", "1.0.228"), &["default"]))); assert!(tree .variants - .contains(&variant(path_key("local", "0.1.0"), &[]))); + .contains(&Variant::new(path_key("local", "0.1.0"), &[]))); let git = tree .packages() .into_iter() @@ -181,7 +174,7 @@ mod tests { ); assert!(tree .variants - .contains(&variant(path_key("local_macro", "0.1.0"), &[]))); + .contains(&Variant::new(path_key("local_macro", "0.1.0"), &[]))); assert_eq!(tree.variants.len(), 6); assert!(tree .edges diff --git a/allow-list/src/input/mod.rs b/allow-list/src/input/mod.rs index 2d31d3a..51f37bc 100644 --- a/allow-list/src/input/mod.rs +++ b/allow-list/src/input/mod.rs @@ -28,6 +28,16 @@ struct Variant { features: BTreeSet, } +#[cfg(test)] +impl Variant { + fn new(key: PackageKey, features: &[&str]) -> Self { + Self { + key, + features: features.iter().map(|f| f.to_string()).collect(), + } + } +} + /// The build evidence for one target #[derive(Debug, Clone)] pub(crate) enum TargetInput { @@ -193,19 +203,12 @@ mod tests { const TREE: &str = "0app v1.0.0 (/build/app)|default\n1serde v1.0.0|std\n1cc v1.0.0|\n"; const RUNTIME: &str = "0app v1.0.0 (/build/app)|default\n1serde v1.0.0|std\n"; - fn variant(key: PackageKey, features: &[&str]) -> Variant { - Variant { - key, - features: features.iter().map(|f| f.to_string()).collect(), - } - } - fn log() -> BuildLog { BuildLog { variants: BTreeSet::from([ - variant(path_key("app", "1.0.0"), &["default"]), - variant(key("serde", "1.0.0"), &["std"]), - variant(key("cc", "1.0.0"), &[]), + Variant::new(path_key("app", "1.0.0"), &["default"]), + Variant::new(key("serde", "1.0.0"), &["std"]), + Variant::new(key("cc", "1.0.0"), &[]), ]), products: BTreeSet::from([path_key("app", "1.0.0")]), } @@ -228,12 +231,16 @@ mod tests { #[test] fn rejects_a_package_missing_from_either_side() { let mut dropped = log(); - dropped.variants.remove(&variant(key("cc", "1.0.0"), &[])); + dropped + .variants + .remove(&Variant::new(key("cc", "1.0.0"), &[])); assert!(graph(&dropped, TREE, RUNTIME) .unwrap_err() .contains("cc@1.0.0")); let mut extra = log(); - extra.variants.insert(variant(key("ring", "1.0.0"), &[])); + extra + .variants + .insert(Variant::new(key("ring", "1.0.0"), &[])); assert!(graph(&extra, TREE, RUNTIME) .unwrap_err() .contains("ring@1.0.0")); @@ -244,10 +251,10 @@ mod tests { let mut other = log(); other .variants - .remove(&variant(key("serde", "1.0.0"), &["std"])); + .remove(&Variant::new(key("serde", "1.0.0"), &["std"])); other .variants - .insert(variant(key("serde", "1.0.0"), &["std", "derive"])); + .insert(Variant::new(key("serde", "1.0.0"), &["std", "derive"])); let err = graph(&other, TREE, RUNTIME).unwrap_err(); assert!(err.contains("variants"), "{err}"); } diff --git a/allow-list/src/inventory.rs b/allow-list/src/inventory.rs index 67d0892..a737a26 100644 --- a/allow-list/src/inventory.rs +++ b/allow-list/src/inventory.rs @@ -192,7 +192,8 @@ fn declared_license(package: &Package) -> DeclaredLicense { #[cfg(test)] pub(crate) mod test_util { - use crate::graph::{PackageKey, SourceKind}; + use crate::graph::test_util::{graph, path_key}; + use crate::graph::{PackageKey, Role, SourceKind, TargetGraph}; use cargo_metadata::Metadata; use serde_json::{json, Value}; @@ -257,28 +258,26 @@ pub(crate) mod test_util { })) .unwrap() } + + /// Metadata and the graph of a workspace root `app 1.0.0` that depends directly on each of + /// the given (package, declared license, role) + pub(crate) fn app_with(deps: &[(PackageKey, Option<&str>, Role)]) -> (Metadata, TargetGraph) { + let app = path_key("app", "1.0.0"); + let mut packages: Vec<(PackageKey, Option<&str>)> = + deps.iter().map(|(k, l, _)| (k.clone(), *l)).collect(); + packages.push((app.clone(), None)); + let members: Vec<(&PackageKey, Role)> = deps.iter().map(|(k, _, r)| (k, *r)).collect(); + let edges: Vec<(&PackageKey, &PackageKey)> = + deps.iter().map(|(k, _, _)| (&app, k)).collect(); + (metadata(&packages), graph(&app, &members, &edges)) + } } #[cfg(test)] mod tests { use super::test_util::metadata; use super::*; - use crate::graph::test_util::{key, path_key}; - - fn graph( - root: &PackageKey, - packages: &[(&PackageKey, Role)], - edges: &[(&PackageKey, &PackageKey)], - ) -> TargetGraph { - let mut members: BTreeMap = - packages.iter().map(|(k, r)| ((*k).clone(), *r)).collect(); - members.insert(root.clone(), Role::Runtime); - let edges = edges - .iter() - .map(|(a, b)| ((*a).clone(), (*b).clone())) - .collect(); - TargetGraph::new(root.clone(), members, edges).unwrap() - } + use crate::graph::test_util::{graph, key, path_key}; fn names<'a>(inventory: &'a Inventory, role: Role) -> Vec<&'a str> { inventory @@ -348,6 +347,19 @@ mod tests { assert!(!tool.first_party); } + #[test] + fn runtime_wins_whatever_the_target_order() { + let app = path_key("app", "1.0.0"); + let cc = key("cc", "1.0.0"); + let meta = metadata(&[(app.clone(), None), (cc.clone(), Some("MIT"))]); + let build_time = || graph(&app, &[(&cc, Role::BuildTime)], &[]); + let runtime = || graph(&app, &[(&cc, Role::Runtime)], &[]); + for graphs in [[build_time(), runtime()], [runtime(), build_time()]] { + let inventory = build(&graphs, &meta, |_| false).unwrap(); + assert_eq!(inventory.components[0].role, Role::Runtime); + } + } + #[test] fn rejects_a_root_that_is_not_a_workspace_member() { let root = key("x", "1.0.0"); diff --git a/allow-list/src/sbom.rs b/allow-list/src/sbom.rs index 073ce2e..ceae57b 100644 --- a/allow-list/src/sbom.rs +++ b/allow-list/src/sbom.rs @@ -234,9 +234,8 @@ mod tests { use crate::approval; use crate::config::Config; use crate::graph::test_util::{key, path_key}; - use crate::graph::{PackageKey, TargetGraph}; - use crate::inventory::{self, test_util::metadata}; - use std::collections::{BTreeMap, BTreeSet}; + use crate::graph::PackageKey; + use crate::inventory::{self, test_util::app_with}; const HASH_A: &str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; const HASH_B: &str = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; @@ -265,22 +264,17 @@ mod tests { deps: &[(PackageKey, Option<&str>, Role)], checksums: Option<&Checksums>, ) -> Result { - let app = path_key("app", "1.0.0"); - let mut packages: Vec<(PackageKey, Option<&str>)> = - deps.iter().map(|(k, l, _)| (k.clone(), *l)).collect(); - packages.push((app.clone(), None)); - let meta = metadata(&packages); - let mut members: BTreeMap = - deps.iter().map(|(k, _, r)| (k.clone(), *r)).collect(); - members.insert(app.clone(), Role::Runtime); - let edges: BTreeSet<_> = deps - .iter() - .map(|(k, _, _)| (app.clone(), k.clone())) - .collect(); - let graph = TargetGraph::new(app, members, edges)?; + render_with(deps, checksums, &config()) + } + + fn render_with( + deps: &[(PackageKey, Option<&str>, Role)], + checksums: Option<&Checksums>, + config: &Config, + ) -> Result { + let (meta, graph) = app_with(deps); let inventory = inventory::build(&[graph], &meta, |_| false)?; - let config = config(); - let validated = approval::validate(inventory, &config)?; + let validated = approval::validate(inventory, config)?; let options = Options { checksums, omit_serial_number: true, @@ -400,4 +394,13 @@ mod tests { .unwrap_err(); assert!(err.to_string().contains("share the reference"), "{err}"); } + + #[test] + fn requires_a_commercial_license() { + let mut config = config(); + config.commercial_license = None; + let deps = [(key("serde", "1.0.0"), Some("MIT"), Role::Runtime)]; + let err = render_with(&deps, None, &config).unwrap_err(); + assert!(err.to_string().contains("commercial_license"), "{err}"); + } } From bf3d8071dca880c3e493cb13cd7d85993eda8b82 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 14:11:37 -0700 Subject: [PATCH 07/12] Remove the cargo-cyclonedx commands; consolidate and encapsulate Architecture review (Claude and Codex): - remove gen-licenses / gen-licenses-dir: BOM scope always comes from the build, so reading cargo-cyclonedx output has no place in the tool - licenses.rs is now only the report renderer (`licenses::write`, the counterpart of `sbom::write`) and renders straight from the validated inventory, without config lookups or unreachable error paths - one definition per license (SPDX id and text; the URL is derived) instead of four parallel matches - ValidatedInventory fields are private: only approval constructs it - config entries named for what they are (ThirdPartyEntry, VendorEntry) - the target-directory convention moved into `input` with the other file-name knowledge; doc fixes (Runtime, TargetInput, third_party) - golden test pinning the license report format byte for byte Report and SBOM output verified identical before and after on the dnp3 fixture and on the merged, JNI and cross-musl evidence. --- CHANGELOG.md | 13 +- README.md | 9 +- allow-list/src/approval.rs | 75 +- allow-list/src/cli.rs | 27 +- allow-list/src/commands.rs | 20 +- allow-list/src/config.rs | 130 +-- allow-list/src/golden_tests.rs | 20 +- allow-list/src/graph.rs | 3 +- allow-list/src/input/mod.rs | 20 +- allow-list/src/licenses.rs | 214 +--- allow-list/src/main.rs | 10 +- allow-list/src/sbom.rs | 8 +- .../tests/fixtures/cyclonedx/a/bom.json | 1 - .../tests/fixtures/cyclonedx/allowed.json | 9 - .../tests/fixtures/cyclonedx/b/bom.json | 1 - .../tests/fixtures/cyclonedx/expected-dir.txt | 84 -- .../fixtures/cyclonedx/expected-single.txt | 78 -- .../tests/fixtures/dnp3/expected-licenses.txt | 932 ++++++++++++++++++ 18 files changed, 1114 insertions(+), 540 deletions(-) delete mode 100644 allow-list/tests/fixtures/cyclonedx/a/bom.json delete mode 100644 allow-list/tests/fixtures/cyclonedx/allowed.json delete mode 100644 allow-list/tests/fixtures/cyclonedx/b/bom.json delete mode 100644 allow-list/tests/fixtures/cyclonedx/expected-dir.txt delete mode 100644 allow-list/tests/fixtures/cyclonedx/expected-single.txt create mode 100644 allow-list/tests/fixtures/dnp3/expected-licenses.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 559284a..3087c65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,10 @@ they are not a library API compatibility promise. ## [0.3.0] - 2026-10-09 -Breaking: `gen-licenses-log` and `gen-licenses-log-dir` take new inputs and arguments, and -their output changes (see below). See the README for how to produce the inputs. +Breaking: the cargo-cyclonedx commands are removed, and `gen-licenses-log` / +`gen-licenses-log-dir` take new inputs and arguments and their output changes (see below). +See the README for how to produce the inputs. Consumers that install from `main` without a +tag should pin `--tag 0.2.1` until they migrate. ### Added @@ -39,9 +41,12 @@ their output changes (see below). See the README for how to produce the inputs. (proc-macros and their dependencies, build-script dependencies) are no longer listed, and first-party crates are matched by name and version instead of being skipped. -### Deprecated +### Removed -- `gen-licenses` / `gen-licenses-dir` (cargo-cyclonedx input). Their output is unchanged. +- `gen-licenses` / `gen-licenses-dir`. They read `cargo cyclonedx` SBOMs, which describe the + dependency graph for cargo-cyclonedx's own feature selection rather than the features the + product was built with (e.g. dnp3 1.7.0's report listed `ring` and omitted `aws-lc-*` for + targets built with `tls-aws-lc`). ## [0.2.1] - 2026-07-22 diff --git a/README.md b/README.md index 6f0f8bc..259302d 100644 --- a/README.md +++ b/README.md @@ -76,10 +76,6 @@ allow-list gen-sbom-log-dir -l evidence --root-package dnp3-ffi -m metadata.json - `--omit-serial-number`: with `SOURCE_DATE_EPOCH` (used as the timestamp), output is byte-for-byte reproducible. -`gen-licenses` / `gen-licenses-dir` read `cargo cyclonedx` SBOMs. They are **deprecated**: -`cargo cyclonedx` describes the dependency graph for its own feature selection, not the -features the product was built with. - ## `allowed.json` ```jsonc @@ -99,9 +95,8 @@ features the product was built with. } ``` -Rules, checked by the build-evidence commands (`gen-licenses-log*`, `gen-sbom-log*`; all -violations are reported together). Workspace members are our own code and need no entry; the -root package must be one. +Rules, checked on every run (all violations are reported together). Workspace members are +our own code and need no entry; the root package must be one. - every compiled package outside the workspace is in **exactly one** list; - a runtime package outside the workspace must be in `third_party` or `vendor`; a `build_only` diff --git a/allow-list/src/approval.rs b/allow-list/src/approval.rs index f9f1150..a918dea 100644 --- a/allow-list/src/approval.rs +++ b/allow-list/src/approval.rs @@ -3,7 +3,7 @@ //! The inventory decides what each package is and how it is used; the configuration must //! approve exactly that. Every violation is collected and reported at once. -use crate::config::{Config, License, Package as ApprovedPackage, VendorPackage}; +use crate::config::{Config, License, ThirdPartyEntry, VendorEntry}; use crate::graph::Role; use crate::inventory::{Component, DeclaredLicense, Inventory}; use anyhow::anyhow; @@ -13,14 +13,14 @@ use spdx::LicenseReq; use std::collections::{BTreeMap, BTreeSet}; /// How a component is approved -#[derive(Debug)] +#[derive(Clone, Copy, Debug)] pub(crate) enum Approval<'c> { /// A workspace member: our own code FirstParty, /// An open-source package whose license was reviewed - ThirdParty(&'c ApprovedPackage), + ThirdParty(&'c ThirdPartyEntry), /// A package the vendor licenses to the customer under its commercial license - Vendor(&'c VendorPackage), + Vendor(&'c VendorEntry), /// A package approved for use at build time only BuildOnly, } @@ -32,28 +32,48 @@ pub(crate) struct Approved<'m, 'c> { pub(crate) approval: Approval<'c>, } -/// An inventory in which every component is approved for the way it is used +/// An inventory in which every component is approved for the way it is used. +/// +/// Only [`validate`] constructs one, so renderers can rely on every component being approved. #[derive(Debug)] pub(crate) struct ValidatedInventory<'m, 'c> { - pub(crate) root: &'m Package, - pub(crate) components: Vec>, - pub(crate) edges: BTreeSet<(&'m PackageId, &'m PackageId)>, + root: &'m Package, + components: Vec>, + edges: BTreeSet<(&'m PackageId, &'m PackageId)>, } -impl ValidatedInventory<'_, '_> { - /// The open-source packages that ship in the product, for the license report: - /// runtime components approved as `third_party`, by name with all their versions - pub(crate) fn shipped_third_party(&self) -> BTreeMap> { - let mut shipped: BTreeMap> = BTreeMap::new(); +impl<'m, 'c> ValidatedInventory<'m, 'c> { + /// The product itself (a workspace member) + pub(crate) fn root(&self) -> &'m Package { + self.root + } + + /// Every other package, sorted by name, version and id + pub(crate) fn components(&self) -> &[Approved<'m, 'c>] { + &self.components + } + + /// Package-level dependency edges, including those from the root + pub(crate) fn edges(&self) -> &BTreeSet<(&'m PackageId, &'m PackageId)> { + &self.edges + } + + /// The open-source packages that ship in the product (runtime components approved as + /// `third_party`), by name, with their reviewed entry and every shipped version + pub(crate) fn shipped_third_party( + &self, + ) -> BTreeMap<&'m str, (&'c ThirdPartyEntry, BTreeSet<&'m Version>)> { + let mut shipped: BTreeMap<&str, (&ThirdPartyEntry, BTreeSet<&Version>)> = BTreeMap::new(); for approved in &self.components { - if approved.component.role == Role::Runtime - && matches!(approved.approval, Approval::ThirdParty(_)) + if let (Approval::ThirdParty(entry), Role::Runtime) = + (approved.approval, approved.component.role) { let package = approved.component.package; shipped - .entry(package.name.clone()) - .or_default() - .insert(package.version.clone()); + .entry(package.name.as_str()) + .or_insert_with(|| (entry, BTreeSet::new())) + .1 + .insert(&package.version); } } shipped @@ -143,7 +163,7 @@ fn approve<'c>(component: &Component, config: &'c Config) -> Result } /// A `third_party` entry must be well formed, however the package is used -fn check_entry(name: &str, approved: &ApprovedPackage) -> Result<(), String> { +fn check_entry(name: &str, approved: &ThirdPartyEntry) -> Result<(), String> { if approved.id != name { return Err(format!( "`third_party` entry is keyed `{name}` but has id `{}`", @@ -153,11 +173,7 @@ fn check_entry(name: &str, approved: &ApprovedPackage) -> Result<(), String> { if approved.licenses.is_empty() { return Err("`third_party` entry has no licenses".to_string()); } - if approved - .licenses - .iter() - .any(|l| matches!(l, License::Unknown)) - { + if approved.licenses.iter().any(|l| l.info().is_none()) { return Err("`third_party` entry has an `Unknown` license".to_string()); } Ok(()) @@ -166,7 +182,7 @@ fn check_entry(name: &str, approved: &ApprovedPackage) -> Result<(), String> { /// The reviewed licenses must still be part of the declared expression (no stale extras) and /// must satisfy it (no newly mandatory licenses) fn check_reviewed_license( - approved: &ApprovedPackage, + approved: &ThirdPartyEntry, declared: &DeclaredLicense, ) -> Result<(), String> { let expression = match declared { @@ -182,10 +198,11 @@ fn check_reviewed_license( let reviewed: Vec = approved .licenses .iter() - .map(|l| { - spdx::license_id(l.spdx_short()) + .filter_map(License::info) + .map(|info| { + spdx::license_id(info.spdx) .map(LicenseReq::from) - .ok_or_else(|| format!("reviewed license {} is not an SPDX id", l.spdx_short())) + .ok_or_else(|| format!("reviewed license {} is not an SPDX id", info.spdx)) }) .collect::>()?; let reviewed_names = || { @@ -371,7 +388,7 @@ mod tests { json["third_party"]["regex"] = mit("regex"); let config = config(json); let validated = validate(inventory, &config).unwrap(); - let shipped: Vec = validated.shipped_third_party().into_keys().collect(); + let shipped: Vec<&str> = validated.shipped_third_party().into_keys().collect(); assert_eq!(shipped, ["serde"]); } } diff --git a/allow-list/src/cli.rs b/allow-list/src/cli.rs index b953d72..2949bef 100644 --- a/allow-list/src/cli.rs +++ b/allow-list/src/cli.rs @@ -1,5 +1,5 @@ -use crate::commands::{target_dirs, Evidence, SbomOptions}; -use crate::input::TargetInput; +use crate::commands::{Evidence, SbomOptions}; +use crate::input::{target_dirs, TargetInput}; use clap::{Args, Parser, Subcommand}; use std::path::PathBuf; @@ -15,29 +15,6 @@ pub(crate) struct Cli { #[allow(clippy::enum_variant_names)] #[derive(Subcommand)] pub(crate) enum Commands { - /// outputs a human-readable report of all 3rd party licenses - /// (deprecated: reads a cargo-cyclonedx SBOM, which does not reflect the features actually built) - GenLicenses { - /// path to the cyclonedx JSON - #[clap(value_parser, long, short = 'b')] - bom_path: PathBuf, - /// path to the JSON configuration (allow-list) - #[clap(value_parser, long, short = 'c')] - config_path: PathBuf, - }, - /// outputs a human-readable report of all 3rd party licenses - /// (deprecated: reads cargo-cyclonedx SBOMs, which do not reflect the features actually built) - GenLicensesDir { - /// list all the directories in this directory - #[clap(value_parser, long, short = 'l')] - list_dir: PathBuf, - /// name of the BOM file in each directory - #[clap(value_parser, long, short = 'b')] - bom_file: String, - /// path to the JSON configuration (allow-list) - #[clap(value_parser, long, short = 'c')] - config_path: PathBuf, - }, /// outputs a human-readable report of the 3rd party licenses that ship in the product, /// from the build evidence of one target GenLicensesLog { diff --git a/allow-list/src/commands.rs b/allow-list/src/commands.rs index 7e55b57..ebf545b 100644 --- a/allow-list/src/commands.rs +++ b/allow-list/src/commands.rs @@ -9,7 +9,7 @@ use anyhow::{anyhow, Context}; use cargo_metadata::Metadata; use cyclonedx_bom::prelude::DateTime; use serde::de::DeserializeOwned; -use std::fs::{read_dir, File}; +use std::fs::File; use std::io::{BufReader, Write}; use std::path::{Path, PathBuf}; use time::format_description::well_known::Rfc3339; @@ -27,28 +27,12 @@ pub(crate) struct Evidence { pub(crate) config: PathBuf, } -/// One target per immediate subdirectory of `dir`, in sorted order -pub(crate) fn target_dirs(dir: &Path) -> Result, anyhow::Error> { - let mut dirs = Vec::new(); - for entry in read_dir(dir).with_context(|| format!("listing {}", dir.display()))? { - let path = entry?.path(); - if path.is_dir() { - dirs.push(path); - } - } - if dirs.is_empty() { - return Err(anyhow!("{} has no target subdirectories", dir.display())); - } - dirs.sort(); - Ok(dirs.iter().map(|d| TargetInput::from_dir(d)).collect()) -} - /// Write the human-readable report of the open-source licenses that ship in the product pub(crate) fn gen_licenses(evidence: &Evidence, w: W) -> Result<(), anyhow::Error> { let config: Config = load_json(&evidence.config)?; let metadata: Metadata = load_json(&evidence.metadata)?; let validated = validate(evidence, &metadata, &config)?; - licenses::gen_licenses_for(&validated.shipped_third_party(), &config, w) + licenses::write(&validated, w) } /// Options of the SBOM commands diff --git a/allow-list/src/config.rs b/allow-list/src/config.rs index ac0d10c..b7961fa 100644 --- a/allow-list/src/config.rs +++ b/allow-list/src/config.rs @@ -28,14 +28,21 @@ pub(crate) enum Source { CratesIo, } -/// Information about a license +/// What the tool knows about a supported license pub(crate) struct LicenseInfo { - /// URL of the license - pub(crate) url: &'static str, - /// Text of the license + /// SPDX identifier + pub(crate) spdx: &'static str, + /// Full text, appended to the license report pub(crate) text: &'static str, } +impl LicenseInfo { + /// The license's page on spdx.org + pub(crate) fn url(&self) -> String { + format!("https://spdx.org/licenses/{}.html", self.spdx) + } +} + /// License type #[derive(Serialize, Deserialize, Debug)] pub(crate) enum License { @@ -70,9 +77,9 @@ pub(crate) enum License { Apache2, } -/// Information about a dependency +/// An allow-list entry for an open-source package whose license was reviewed #[derive(Serialize, Deserialize, Debug)] -pub(crate) struct Package { +pub(crate) struct ThirdPartyEntry { /// id of the allowed package pub(crate) id: String, /// Where the package came from @@ -85,7 +92,7 @@ pub(crate) struct Package { pub(crate) embedded: bool, } -impl Package { +impl ThirdPartyEntry { pub(crate) fn url(&self) -> String { match self.source { Source::CratesIo => format!("https://crates.io/crates/{}", self.id), @@ -93,12 +100,13 @@ impl Package { } } -/// Information about a vendor package +/// An allow-list entry for a package the vendor licenses to the customer under its commercial +/// license #[derive(Serialize, Deserialize, Debug)] -pub(crate) struct VendorPackage { +pub(crate) struct VendorEntry { /// SCM URL where the package is located pub(crate) url: String, - /// see [`Package::embedded`] + /// see [`ThirdPartyEntry::embedded`] #[serde(default)] pub(crate) embedded: bool, } @@ -117,10 +125,10 @@ pub(crate) struct CommercialLicense { pub(crate) struct Config { /// packages approved for use at build time only (not linked or distributed); license not reviewed pub(crate) build_only: BTreeSet, - /// packages that are licensed by the vendor and are distributed under a custom license - pub(crate) vendor: BTreeMap, - /// 3rd party packages that are allowed to be build dependencies - pub(crate) third_party: BTreeMap, + /// packages licensed to the customer by the vendor under its commercial license + pub(crate) vendor: BTreeMap, + /// open-source packages whose license was reviewed; approved to ship and to build + pub(crate) third_party: BTreeMap, /// license of first-party and vendor packages, required to generate an SBOM #[serde(default)] pub(crate) commercial_license: Option, @@ -135,77 +143,37 @@ impl Config { } impl License { - /// Information about the license - pub(crate) fn info(&self) -> LicenseInfo { - LicenseInfo { - url: self.url(), - text: self.text(), - } + /// The license's SPDX id and text, or `None` for `Unknown` (which approval rejects) + pub(crate) fn info(&self) -> Option { + let (spdx, text) = match self { + License::Unknown => return None, + License::Isc { .. } => ("ISC", include_str!("../licenses/isc.txt")), + License::Mit { .. } => ("MIT", include_str!("../licenses/mit.txt")), + License::OpenSsl => ("OpenSSL", include_str!("../licenses/openssl.txt")), + License::Bsl1 => ("BSL-1.0", include_str!("../licenses/bsl.txt")), + License::Mpl2 => ("MPL-2.0", include_str!("../licenses/mpl2.txt")), + License::Bsd3 { .. } => ("BSD-3-Clause", include_str!("../licenses/bsd3.txt")), + License::UnicodeDfs2016 => ( + "Unicode-DFS-2016", + include_str!("../licenses/unicode_dfs_2016.txt"), + ), + License::Apache2 => ("Apache-2.0", include_str!("../licenses/apache2.txt")), + }; + Some(LicenseInfo { spdx, text }) } - /// Optional copyright lines provided by the author(s) + /// Copyright lines recorded in the review, for licenses that require them pub(crate) fn copyright(&self) -> Option> { match self { - License::Unknown => None, - License::Isc { copyright } => Some(copyright.lines()), - License::Mit { copyright } => Some(copyright.lines()), - License::OpenSsl => None, - License::Bsl1 => None, - License::Mpl2 => None, - License::Bsd3 { copyright } => Some(copyright.lines()), - License::UnicodeDfs2016 => None, - License::Apache2 => None, - } - } - - /// The text of the license itself - pub(crate) fn text(&self) -> &'static str { - match self { - License::Isc { .. } => std::include_str!("../licenses/isc.txt"), - License::Mit { .. } => std::include_str!("../licenses/mit.txt"), - License::OpenSsl => std::include_str!("../licenses/openssl.txt"), - License::Bsl1 => std::include_str!("../licenses/bsl.txt"), - License::Mpl2 => std::include_str!("../licenses/mpl2.txt"), - License::Bsd3 { .. } => std::include_str!("../licenses/bsd3.txt"), - License::UnicodeDfs2016 => { - std::include_str!("../licenses/unicode_dfs_2016.txt") - } - License::Apache2 => std::include_str!("../licenses/apache2.txt"), - License::Unknown => panic!("You must define unknown licenses"), - } - } - - /// SPDX short abbreviation for the license - pub(crate) fn spdx_short(&self) -> &'static str { - match self { - License::Isc { .. } => "ISC", - License::Mit { .. } => "MIT", - License::OpenSsl => "OpenSSL", - License::Bsl1 => "BSL-1.0", - License::Mpl2 => "MPL-2.0", - License::Bsd3 { .. } => "BSD-3-Clause", - License::UnicodeDfs2016 => "Unicode-DFS-2016", - License::Apache2 => "Apache-2.0", - License::Unknown => { - panic!("You must define unknown licenses") - } - } - } - - /// The URL with information about the license - pub(crate) fn url(&self) -> &'static str { - match self { - License::Isc { .. } => "https://spdx.org/licenses/ISC.html", - License::Mit { .. } => "https://spdx.org/licenses/MIT.html", - License::OpenSsl => "https://spdx.org/licenses/OpenSSL.html", - License::Bsl1 => "https://spdx.org/licenses/BSL-1.0.html", - License::Mpl2 => "https://spdx.org/licenses/MPL-2.0.html", - License::Bsd3 { .. } => "https://spdx.org/licenses/BSD-3-Clause.html", - License::UnicodeDfs2016 => "https://spdx.org/licenses/Unicode-DFS-2016.html", - License::Apache2 => "https://spdx.org/licenses/Apache-2.0.html", - License::Unknown => { - panic!("You must define unknown licenses") - } + License::Isc { copyright } + | License::Mit { copyright } + | License::Bsd3 { copyright } => Some(copyright.lines()), + License::Unknown + | License::OpenSsl + | License::Bsl1 + | License::Mpl2 + | License::UnicodeDfs2016 + | License::Apache2 => None, } } } diff --git a/allow-list/src/golden_tests.rs b/allow-list/src/golden_tests.rs index ca93cb4..294f4d3 100644 --- a/allow-list/src/golden_tests.rs +++ b/allow-list/src/golden_tests.rs @@ -5,10 +5,10 @@ //! The expected roles of the `aws` target were derived independently from Cargo's nightly SBOM //! precursor file for the same build (`normal`-edge reachability from the root). -use crate::commands::{self, target_dirs, Evidence, SbomOptions}; +use crate::commands::{self, Evidence, SbomOptions}; use crate::config::Config; use crate::graph::Role; -use crate::input::TargetInput; +use crate::input::{target_dirs, TargetInput}; use crate::sbom::{self, Checksums}; use cargo_metadata::Metadata; use cyclonedx_bom::prelude::*; @@ -194,11 +194,11 @@ fn roles(evidence: &Evidence, config: &Config) -> BTreeMap { let metadata: Metadata = load("metadata.json"); let validated = commands::validate(evidence, &metadata, config).unwrap(); let mut roles: BTreeMap = validated - .components + .components() .iter() .map(|a| (a.component.package.name.clone(), a.component.role)) .collect(); - roles.insert(validated.root.name.clone(), Role::Runtime); + roles.insert(validated.root().name.clone(), Role::Runtime); roles } @@ -302,6 +302,18 @@ fn license_report_lists_exactly_the_shipped_third_party_crates() { assert_eq!(names, expected); } +#[test] +fn license_report_format_is_unchanged() { + // consumers ship this file verbatim as third-party-licenses.txt + let mut out = Vec::new(); + commands::gen_licenses(&all_targets(), &mut out).unwrap(); + let expected = std::fs::read_to_string(fixture("expected-licenses.txt")).unwrap(); + assert!( + String::from_utf8(out).unwrap() == expected, + "license report differs from expected-licenses.txt" + ); +} + #[test] fn license_report_and_sbom_agree_on_every_shipped_version() { assert_eq!( diff --git a/allow-list/src/graph.rs b/allow-list/src/graph.rs index dc69573..ba45bd2 100644 --- a/allow-list/src/graph.rs +++ b/allow-list/src/graph.rs @@ -57,7 +57,8 @@ impl fmt::Display for PackageKey { pub(crate) enum Role { /// Only used to build the product (build scripts, proc-macros and their dependencies) BuildTime, - /// Linked into the product + /// Ships in the product: linked into it, or (after the core applies the config's + /// `embedded` flag) a build-time dependency whose own code is copied into it Runtime, } diff --git a/allow-list/src/input/mod.rs b/allow-list/src/input/mod.rs index 51f37bc..ad393ab 100644 --- a/allow-list/src/input/mod.rs +++ b/allow-list/src/input/mod.rs @@ -42,7 +42,8 @@ impl Variant { #[derive(Debug, Clone)] pub(crate) enum TargetInput { /// A `cargo build --message-format json` log plus the full (`-e normal,build`) and runtime - /// (`-e normal,no-proc-macro`) `cargo tree` outputs from the same invocation + /// (`-e normal,no-proc-macro`) `cargo tree` outputs, run with the same arguments in the + /// build's environment LogAndTree { log: PathBuf, tree: PathBuf, @@ -58,6 +59,23 @@ impl std::fmt::Display for TargetInput { } } +/// The evidence of every target: one per immediate subdirectory of `dir`, in sorted order, +/// each holding the standard file names +pub(crate) fn target_dirs(dir: &Path) -> Result, anyhow::Error> { + let mut dirs = Vec::new(); + for entry in std::fs::read_dir(dir).with_context(|| format!("listing {}", dir.display()))? { + let path = entry?.path(); + if path.is_dir() { + dirs.push(path); + } + } + if dirs.is_empty() { + return Err(anyhow!("{} has no target subdirectories", dir.display())); + } + dirs.sort(); + Ok(dirs.iter().map(|d| TargetInput::from_dir(d)).collect()) +} + impl TargetInput { /// The evidence for one target stored in a directory under the standard file names pub(crate) fn from_dir(dir: &Path) -> Self { diff --git a/allow-list/src/licenses.rs b/allow-list/src/licenses.rs index a5ad538..f8a5464 100644 --- a/allow-list/src/licenses.rs +++ b/allow-list/src/licenses.rs @@ -1,101 +1,25 @@ -use crate::config::{Config, LicenseInfo}; -use anyhow::anyhow; -use cyclonedx_bom::prelude::Bom; -use semver::Version; -use std::collections::btree_map::Entry; -use std::collections::{BTreeMap, BTreeSet}; -use std::fs::{read_dir, File}; -use std::io::Write; -use std::path::Path; - -/// Generate a license summary file from a build log and configuration file -pub(crate) fn gen_licenses( - bom_path: &Path, - config_path: &Path, - w: W, -) -> Result<(), anyhow::Error> -where - W: Write, -{ - let bom = Bom::parse_from_json_v1_4(File::open(bom_path)?)?; - let config: Config = serde_json::from_reader(File::open(config_path)?)?; - - let components = extract_deps(bom, &config)?; - - gen_licenses_for(&components, &config, w)?; - - Ok(()) -} - -/// Generate a license summary file from a build log and configuration file -pub(crate) fn gen_licenses_in_dirs( - list_dir: &Path, - bom_file: &str, - config_path: &Path, - w: W, -) -> Result<(), anyhow::Error> -where - W: Write, -{ - let config: Config = serde_json::from_reader(File::open(config_path)?)?; - let mut components: BTreeMap> = BTreeMap::new(); - - for item in read_dir(list_dir)? { - let item = item?; - if item.file_type()?.is_dir() { - let bom = Bom::parse_from_json_v1_4(File::open(item.path().join(bom_file))?)?; - for (name, versions) in extract_deps(bom, &config)? { - match components.entry(name.clone()) { - Entry::Vacant(x) => { - x.insert(versions); - } - Entry::Occupied(mut occ) => { - for version in versions { - occ.get_mut().insert(version); - } - } - } - } - } - } - - gen_licenses_for(&components, &config, w)?; +//! Renderer: the human-readable report of the open-source licenses that ship in the product - Ok(()) -} +use crate::approval::ValidatedInventory; +use crate::config::LicenseInfo; +use std::collections::BTreeMap; +use std::io::Write; -/// Generate a license summary file from a build log and configuration file -pub(crate) fn gen_licenses_for( - components: &BTreeMap>, - config: &Config, +/// Write the license report of a validated inventory +pub(crate) fn write( + validated: &ValidatedInventory, mut w: W, -) -> Result<(), anyhow::Error> -where - W: Write, -{ - // first summarize the licenses - let mut licenses: BTreeMap<&'static str, LicenseInfo> = BTreeMap::new(); - let mut disallowed = BTreeSet::new(); +) -> Result<(), anyhow::Error> { + let shipped = validated.shipped_third_party(); - for name in components.keys() { - match config.third_party.get(name) { - Some(pkg) => { - for license in &pkg.licenses { - licenses.insert(license.spdx_short(), license.info()); - } - } - None => { - disallowed.insert(name.to_string()); - } + // every license that applies, once, with its text appended at the end + let mut licenses: BTreeMap<&'static str, LicenseInfo> = BTreeMap::new(); + for (entry, _) in shipped.values() { + for info in entry.licenses.iter().filter_map(|l| l.info()) { + licenses.insert(info.spdx, info); } } - if !disallowed.is_empty() { - return Err(anyhow!( - "These 3rd party packages are not in the allow list: {disallowed:?}" - )); - } - writeln!( w, "This distribution contains open source dependencies under the following licenses:" @@ -103,46 +27,32 @@ where writeln!(w)?; for (spdx, info) in &licenses { writeln!(w, " * {spdx}")?; - writeln!(w, " - {}", info.url)?; + writeln!(w, " - {}", info.url())?; } writeln!(w)?; writeln!(w, "Copies of these licenses are provided at the end of this document. They may also be obtained from the URLs above.")?; writeln!(w)?; - for (name, versions) in components { - let versions: Vec = versions + for (entry, versions) in shipped.values() { + let versions: Vec = versions.iter().map(ToString::to_string).collect(); + let spdx: Vec<&str> = entry + .licenses .iter() - .map(std::string::ToString::to_string) + .filter_map(|l| l.info()) + .map(|info| info.spdx) .collect(); - - let pkg = config - .third_party - .get(name) - .ok_or_else(|| anyhow!("3rd party package {name} not in the allow list"))?; - writeln!(w, "crate: {}", pkg.id)?; + writeln!(w, "crate: {}", entry.id)?; writeln!(w, "version(s): {}", versions.join(", "))?; - writeln!(w, "url: {}", pkg.url())?; - - if pkg.licenses.is_empty() { - return Err(anyhow!("No license specified for {name}",)); - } - - let licenses: Vec = pkg + writeln!(w, "url: {}", entry.url())?; + writeln!(w, "license(s): {}", spdx.join(" AND "))?; + for line in entry .licenses .iter() - .map(|x| x.spdx_short().to_string()) - .collect(); - writeln!(w, "license(s): {}", licenses.join(" AND "))?; - - // write out copyright statements - for lic in &pkg.licenses { - if let Some(lines) = lic.copyright() { - for line in lines { - writeln!(w, "{line}")?; - } - } + .filter_map(|l| l.copyright()) + .flatten() + { + writeln!(w, "{line}")?; } - writeln!(w)?; } @@ -153,67 +63,3 @@ where Ok(()) } - -fn extract_deps( - bom: Bom, - config: &Config, -) -> Result>, anyhow::Error> { - let mut deps: BTreeMap> = BTreeMap::new(); - - let components = &bom - .components - .ok_or_else(|| anyhow!("required field 'components' is 'None'"))? - .0; - - 'deps: for component in components { - let version = component - .version - .as_ref() - .ok_or_else(|| anyhow!("Missing version in component {}", component.name))?; - let version = semver::Version::parse(version)?; - if config.build_only.contains(&*component.name) { - continue 'deps; - } - - if config.vendor.contains_key(&*component.name) { - continue 'deps; - } - - match deps.entry(component.name.to_string()) { - Entry::Vacant(x) => { - x.insert(BTreeSet::from([version])); - } - Entry::Occupied(mut x) => { - x.get_mut().insert(version); - } - } - } - - Ok(deps) -} - -#[cfg(test)] -mod tests { - use super::*; - - fn fixture(path: &str) -> std::path::PathBuf { - Path::new(env!("CARGO_MANIFEST_DIR")) - .join("tests/fixtures/cyclonedx") - .join(path) - } - - /// The deprecated cargo-cyclonedx commands must keep producing exactly the 0.2.1 output - /// (the expected files were generated with the 0.2.1 release) - #[test] - fn cyclonedx_commands_match_0_2_1_output() { - let mut out = Vec::new(); - gen_licenses_in_dirs(&fixture(""), "bom.json", &fixture("allowed.json"), &mut out).unwrap(); - let expected = std::fs::read_to_string(fixture("expected-dir.txt")).unwrap(); - assert_eq!(String::from_utf8(out).unwrap(), expected); - - let mut out = Vec::new(); - gen_licenses(&fixture("a/bom.json"), &fixture("allowed.json"), &mut out).unwrap(); - let expected = std::fs::read_to_string(fixture("expected-single.txt")).unwrap(); - assert_eq!(String::from_utf8(out).unwrap(), expected); - } -} diff --git a/allow-list/src/main.rs b/allow-list/src/main.rs index 237fe8f..49a43d8 100644 --- a/allow-list/src/main.rs +++ b/allow-list/src/main.rs @@ -18,6 +18,7 @@ pub(crate) mod graph; pub(crate) mod input; /// merge per-target graphs and resolve them against the cargo metadata pub(crate) mod inventory; +/// license report renderer pub(crate) mod licenses; /// CycloneDX SBOM renderer pub(crate) mod sbom; @@ -28,15 +29,6 @@ fn main() -> Result<(), anyhow::Error> { let cli = Cli::parse(); match cli.command { - Commands::GenLicenses { - bom_path, - config_path, - } => licenses::gen_licenses(&bom_path, &config_path, stdout()), - Commands::GenLicensesDir { - list_dir, - bom_file, - config_path, - } => licenses::gen_licenses_in_dirs(&list_dir, &bom_file, &config_path, stdout()), Commands::GenLicensesLog { target, common } => { commands::gen_licenses(&target.evidence(common), stdout()) } diff --git a/allow-list/src/sbom.rs b/allow-list/src/sbom.rs index ceae57b..9c796bd 100644 --- a/allow-list/src/sbom.rs +++ b/allow-list/src/sbom.rs @@ -91,9 +91,9 @@ pub(crate) fn write( }; // every package is referenced by its purl, which must therefore be unique - let root = validated.root; + let root = validated.root(); let packages = - std::iter::once(root).chain(validated.components.iter().map(|a| a.component.package)); + std::iter::once(root).chain(validated.components().iter().map(|a| a.component.package)); let mut purls: HashMap<&PackageId, Purl> = HashMap::new(); let mut refs: HashMap<&PackageId, String> = HashMap::new(); let mut unique = HashSet::new(); @@ -122,7 +122,7 @@ pub(crate) fn write( root_component.licenses = Some(commercial()); let mut components = Vec::new(); - for approved in &validated.components { + for approved in validated.components() { let package = approved.component.package; let mut component = component(package); component.scope = Some(match approved.component.role { @@ -165,7 +165,7 @@ pub(crate) fn write( let mut dependencies: BTreeMap<&str, Vec<&str>> = refs.values().map(|r| (r.as_str(), Vec::new())).collect(); - for (from, to) in &validated.edges { + for (from, to) in validated.edges() { if let Some(list) = dependencies.get_mut(refs[from].as_str()) { list.push(refs[to].as_str()); } diff --git a/allow-list/tests/fixtures/cyclonedx/a/bom.json b/allow-list/tests/fixtures/cyclonedx/a/bom.json deleted file mode 100644 index 9c4aca9..0000000 --- a/allow-list/tests/fixtures/cyclonedx/a/bom.json +++ /dev/null @@ -1 +0,0 @@ -{"bomFormat":"CycloneDX","specVersion":"1.4","version":1,"components":[{"type":"library","name":"serde","version":"1.0.228"},{"type":"library","name":"ring","version":"0.17.14"},{"type":"library","name":"cc","version":"1.2.60"},{"type":"library","name":"dnp3","version":"1.7.0"}]} diff --git a/allow-list/tests/fixtures/cyclonedx/allowed.json b/allow-list/tests/fixtures/cyclonedx/allowed.json deleted file mode 100644 index 4b5199c..0000000 --- a/allow-list/tests/fixtures/cyclonedx/allowed.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "build_only": ["cc"], - "vendor": { "dnp3": { "url": "https://github.com/stepfunc/dnp3" } }, - "third_party": { - "serde": { "id": "serde", "source": "crates.io", "licenses": [{ "MIT": { "copyright": "NotPresent" } }] }, - "ring": { "id": "ring", "source": "crates.io", "licenses": [{ "ISC": { "copyright": { "Lines": ["Copyright 2015-2016 Brian Smith."] } } }, "OpenSSL"] }, - "tokio": { "id": "tokio", "source": "crates.io", "licenses": [{ "MIT": { "copyright": { "Lines": ["Copyright (c) Tokio Contributors"] } } }] } - } -} diff --git a/allow-list/tests/fixtures/cyclonedx/b/bom.json b/allow-list/tests/fixtures/cyclonedx/b/bom.json deleted file mode 100644 index 6ca8cd1..0000000 --- a/allow-list/tests/fixtures/cyclonedx/b/bom.json +++ /dev/null @@ -1 +0,0 @@ -{"bomFormat":"CycloneDX","specVersion":"1.4","version":1,"components":[{"type":"library","name":"serde","version":"1.0.219"},{"type":"library","name":"tokio","version":"1.52.1"},{"type":"library","name":"dnp3","version":"1.7.0"}]} diff --git a/allow-list/tests/fixtures/cyclonedx/expected-dir.txt b/allow-list/tests/fixtures/cyclonedx/expected-dir.txt deleted file mode 100644 index 90d4b6c..0000000 --- a/allow-list/tests/fixtures/cyclonedx/expected-dir.txt +++ /dev/null @@ -1,84 +0,0 @@ -This distribution contains open source dependencies under the following licenses: - - * ISC - - https://spdx.org/licenses/ISC.html - * MIT - - https://spdx.org/licenses/MIT.html - * OpenSSL - - https://spdx.org/licenses/OpenSSL.html - -Copies of these licenses are provided at the end of this document. They may also be obtained from the URLs above. - -crate: ring -version(s): 0.17.14 -url: https://crates.io/crates/ring -license(s): ISC AND OpenSSL -Copyright 2015-2016 Brian Smith. - -crate: serde -version(s): 1.0.219, 1.0.228 -url: https://crates.io/crates/serde -license(s): MIT -No copyright statement was provided by the author even though they license may refer to it - -crate: tokio -version(s): 1.52.1 -url: https://crates.io/crates/tokio -license(s): MIT -Copyright (c) Tokio Contributors - -=============================== ISC =========================================== - -Permission to use, copy, modify, and /or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -================================= MIT ========================================= - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -================================ OPENSSL======================================= - -Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software must display the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org. - 5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project. - 6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)" - -THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). This product includes software written by Tim Hudson (tjh@cryptsoft.com). - -Original SSLeay License - -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. - -This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). The implementation was written so as to conform with Netscapes SSL. - -This library is free for commercial and non-commercial use as long as the following conditions are aheared to. The following conditions apply to all code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. The SSL documentation included with this distribution is covered by the same copyright terms except that the holder is Tim Hudson (tjh@cryptsoft.com). - -Copyright remains Eric Young's, and as such any Copyright notices in the code are not to be removed. If this package is used in a product, Eric Young should be given attribution as the author of the parts of the library used. This can be in the form of a textual message at program startup or in documentation (online or textual) provided with the package. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - "This product includes cryptographic software written by Eric Young (eay@cryptsoft.com)" - The word 'cryptographic' can be left out if the rouines from the library being used are not cryptographic related :-). - 4. If you include any Windows specific code (or a derivative thereof) from the apps directory (application code) you must include an acknowledgement: "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - -THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The licence and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distribution licence [including the GNU Public Licence.] - diff --git a/allow-list/tests/fixtures/cyclonedx/expected-single.txt b/allow-list/tests/fixtures/cyclonedx/expected-single.txt deleted file mode 100644 index af02046..0000000 --- a/allow-list/tests/fixtures/cyclonedx/expected-single.txt +++ /dev/null @@ -1,78 +0,0 @@ -This distribution contains open source dependencies under the following licenses: - - * ISC - - https://spdx.org/licenses/ISC.html - * MIT - - https://spdx.org/licenses/MIT.html - * OpenSSL - - https://spdx.org/licenses/OpenSSL.html - -Copies of these licenses are provided at the end of this document. They may also be obtained from the URLs above. - -crate: ring -version(s): 0.17.14 -url: https://crates.io/crates/ring -license(s): ISC AND OpenSSL -Copyright 2015-2016 Brian Smith. - -crate: serde -version(s): 1.0.228 -url: https://crates.io/crates/serde -license(s): MIT -No copyright statement was provided by the author even though they license may refer to it - -=============================== ISC =========================================== - -Permission to use, copy, modify, and /or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -================================= MIT ========================================= - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -================================ OPENSSL======================================= - -Copyright (c) 1998-2008 The OpenSSL Project. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software must display the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact openssl-core@openssl.org. - 5. Products derived from this software may not be called "OpenSSL" nor may "OpenSSL" appear in their names without prior written permission of the OpenSSL Project. - 6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)" - -THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -This product includes cryptographic software written by Eric Young (eay@cryptsoft.com). This product includes software written by Tim Hudson (tjh@cryptsoft.com). - -Original SSLeay License - -Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -All rights reserved. - -This package is an SSL implementation written by Eric Young (eay@cryptsoft.com). The implementation was written so as to conform with Netscapes SSL. - -This library is free for commercial and non-commercial use as long as the following conditions are aheared to. The following conditions apply to all code found in this distribution, be it the RC4, RSA, lhash, DES, etc., code; not just the SSL code. The SSL documentation included with this distribution is covered by the same copyright terms except that the holder is Tim Hudson (tjh@cryptsoft.com). - -Copyright remains Eric Young's, and as such any Copyright notices in the code are not to be removed. If this package is used in a product, Eric Young should be given attribution as the author of the parts of the library used. This can be in the form of a textual message at program startup or in documentation (online or textual) provided with the package. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: - "This product includes cryptographic software written by Eric Young (eay@cryptsoft.com)" - The word 'cryptographic' can be left out if the rouines from the library being used are not cryptographic related :-). - 4. If you include any Windows specific code (or a derivative thereof) from the apps directory (application code) you must include an acknowledgement: "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - -THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The licence and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distribution licence [including the GNU Public Licence.] - diff --git a/allow-list/tests/fixtures/dnp3/expected-licenses.txt b/allow-list/tests/fixtures/dnp3/expected-licenses.txt new file mode 100644 index 0000000..08ed012 --- /dev/null +++ b/allow-list/tests/fixtures/dnp3/expected-licenses.txt @@ -0,0 +1,932 @@ +This distribution contains open source dependencies under the following licenses: + + * Apache-2.0 + - https://spdx.org/licenses/Apache-2.0.html + * BSD-3-Clause + - https://spdx.org/licenses/BSD-3-Clause.html + * BSL-1.0 + - https://spdx.org/licenses/BSL-1.0.html + * ISC + - https://spdx.org/licenses/ISC.html + * MIT + - https://spdx.org/licenses/MIT.html + * MPL-2.0 + - https://spdx.org/licenses/MPL-2.0.html + +Copies of these licenses are provided at the end of this document. They may also be obtained from the URLs above. + +crate: aes +version(s): 0.8.4 +url: https://crates.io/crates/aes +license(s): MIT +Copyright (c) 2018 Artyom Pavlov + +crate: aws-lc-rs +version(s): 1.18.1 +url: https://crates.io/crates/aws-lc-rs +license(s): ISC +No copyright statement was provided by the author even though they license may refer to it + +crate: aws-lc-sys +version(s): 0.45.0 +url: https://crates.io/crates/aws-lc-sys +license(s): ISC AND Apache-2.0 AND MIT AND BSD-3-Clause +No copyright statement was provided by the author even though they license may refer to it +No copyright statement was provided by the author even though they license may refer to it +No copyright statement was provided by the author even though they license may refer to it + +crate: base64 +version(s): 0.22.1 +url: https://crates.io/crates/base64 +license(s): MIT +Copyright (c) 2015 Alice Maz + +crate: base64ct +version(s): 1.8.3 +url: https://crates.io/crates/base64ct +license(s): MIT +Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com) +Copyright (c) 2021 The RustCrypto Project Developers + +crate: bitflags +version(s): 1.3.2, 2.11.1 +url: https://crates.io/crates/bitflags +license(s): MIT +Copyright (c) 2014 The Rust Project Developers + +crate: block-buffer +version(s): 0.10.4 +url: https://crates.io/crates/block-buffer +license(s): MIT +Copyright (c) 2018-2019 The RustCrypto Project Developers + +crate: block-padding +version(s): 0.3.3 +url: https://crates.io/crates/block-padding +license(s): MIT +Copyright (c) 2018-2019 The RustCrypto Project Developers + +crate: bytes +version(s): 1.11.1 +url: https://crates.io/crates/bytes +license(s): MIT +Copyright (c) 2018 Carl Lerche + +crate: cbc +version(s): 0.1.2 +url: https://crates.io/crates/cbc +license(s): MIT +Copyright (c) 2018-2022 RustCrypto Developers +Copyright (c) 2018 Artyom Pavlov + +crate: cfg-if +version(s): 1.0.4 +url: https://crates.io/crates/cfg-if +license(s): MIT +Copyright (c) 2014 Alex Crichton + +crate: chrono +version(s): 0.4.44 +url: https://crates.io/crates/chrono +license(s): MIT +Copyright (c) 2014, Kang Seonghoon + +crate: cipher +version(s): 0.4.4 +url: https://crates.io/crates/cipher +license(s): MIT +Copyright (c) 2016-2020 The RustCrypto Project Developers + +crate: const-oid +version(s): 0.9.6 +url: https://crates.io/crates/const-oid +license(s): MIT +Copyright (c) 2020-2022 The RustCrypto Project Developers + +crate: cpufeatures +version(s): 0.2.17 +url: https://crates.io/crates/cpufeatures +license(s): MIT +Copyright (c) 2020 The RustCrypto Project Developers + +crate: crypto-common +version(s): 0.1.7 +url: https://crates.io/crates/crypto-common +license(s): MIT +Copyright (c) 2021 RustCrypto Developers + +crate: der +version(s): 0.7.10 +url: https://crates.io/crates/der +license(s): MIT +Copyright (c) 2020-2022 The RustCrypto Project Developers + +crate: digest +version(s): 0.10.7 +url: https://crates.io/crates/digest +license(s): MIT +Copyright (c) 2017 Artyom Pavlov + +crate: futures +version(s): 0.3.32 +url: https://crates.io/crates/futures +license(s): MIT +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +crate: futures-channel +version(s): 0.3.32 +url: https://crates.io/crates/futures-channel +license(s): MIT +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +crate: futures-core +version(s): 0.3.32 +url: https://crates.io/crates/futures-core +license(s): MIT +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +crate: futures-executor +version(s): 0.3.32 +url: https://crates.io/crates/futures-executor +license(s): MIT +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +crate: futures-io +version(s): 0.3.32 +url: https://crates.io/crates/futures-io +license(s): MIT +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +crate: futures-sink +version(s): 0.3.32 +url: https://crates.io/crates/futures-sink +license(s): MIT +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +crate: futures-task +version(s): 0.3.32 +url: https://crates.io/crates/futures-task +license(s): MIT +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +crate: futures-util +version(s): 0.3.32 +url: https://crates.io/crates/futures-util +license(s): MIT +Copyright (c) 2016 Alex Crichton +Copyright (c) 2017 The Tokio Authors + +crate: generic-array +version(s): 0.14.7 +url: https://crates.io/crates/generic-array +license(s): MIT +Copyright (c) 2015 Bartłomiej Kamiński + +crate: getrandom +version(s): 0.2.17 +url: https://crates.io/crates/getrandom +license(s): MIT +Copyright (c) 2018-2024 The rust-random Project Developers +Copyright (c) 2014 The Rust Project Developers + +crate: hmac +version(s): 0.12.1 +url: https://crates.io/crates/hmac +license(s): MIT +Copyright (c) 2017 Artyom Pavlov + +crate: iana-time-zone +version(s): 0.1.65 +url: https://crates.io/crates/iana-time-zone +license(s): MIT +Copyright (c) 2020 Andrew D. Straw + +crate: inout +version(s): 0.1.4 +url: https://crates.io/crates/inout +license(s): MIT +Copyright (c) 2022 The RustCrypto Project Developers +Copyright (c) 2022 Artyom Pavlov + +crate: itoa +version(s): 1.0.18 +url: https://crates.io/crates/itoa +license(s): MIT +No copyright statement was provided by the author even though they license may refer to it + +crate: lazy_static +version(s): 1.5.0 +url: https://crates.io/crates/lazy_static +license(s): MIT +Copyright (c) 2010 The Rust Project Developers + +crate: libc +version(s): 0.2.185 +url: https://crates.io/crates/libc +license(s): MIT +Copyright (c) 2014-2020 The Rust Project Developers + +crate: log +version(s): 0.4.29 +url: https://crates.io/crates/log +license(s): MIT +Copyright (c) 2014 The Rust Project Developers + +crate: memchr +version(s): 2.8.0 +url: https://crates.io/crates/memchr +license(s): MIT +Copyright (c) 2015 Andrew Gallant + +crate: mio +version(s): 1.2.0 +url: https://crates.io/crates/mio +license(s): MIT +Copyright (c) 2014 Carl Lerche and other MIO contributors + +crate: mio-serial +version(s): 5.0.6 +url: https://crates.io/crates/mio-serial +license(s): MIT +Copyright (c) 2017 Zac Berkowitz (zac.berkowitz@gmail.com) + +crate: nix +version(s): 0.26.4, 0.29.0 +url: https://crates.io/crates/nix +license(s): MIT +Copyright (c) 2015 Carl Lerche + nix-rust Authors + +crate: nu-ansi-term +version(s): 0.50.3 +url: https://crates.io/crates/nu-ansi-term +license(s): MIT +Copyright (c) 2014 Benjamin Sago +Copyright (c) 2021-2022 The Nushell Project Developers + +crate: num-traits +version(s): 0.2.19 +url: https://crates.io/crates/num-traits +license(s): MIT +Copyright (c) 2014 The Rust Project Developers + +crate: num_cpus +version(s): 1.17.0 +url: https://crates.io/crates/num_cpus +license(s): MIT +Copyright (c) 2015 + +crate: once_cell +version(s): 1.21.4 +url: https://crates.io/crates/once_cell +license(s): MIT +No copyright statement was provided by the author even though they license may refer to it + +crate: oo-bindgen +version(s): 0.8.8 +url: https://crates.io/crates/oo-bindgen +license(s): MIT +Copyright (c) Step Function I/O LLC + +crate: pbkdf2 +version(s): 0.12.2 +url: https://crates.io/crates/pbkdf2 +license(s): MIT +Copyright (c) 2017 Artyom Pavlov +Copyright (c) 2018-2021 The RustCrypto Project Developers + +crate: pem +version(s): 3.0.6 +url: https://crates.io/crates/pem +license(s): MIT +Copyright (c) 2016 Jonathan Creekmore + +crate: pem-rfc7468 +version(s): 0.7.0 +url: https://crates.io/crates/pem-rfc7468 +license(s): MIT +Copyright (c) 2021 The RustCrypto Project Developers + +crate: pin-project-lite +version(s): 0.2.17 +url: https://crates.io/crates/pin-project-lite +license(s): MIT +No copyright statement was provided by the author even though they license may refer to it + +crate: pkcs5 +version(s): 0.7.1 +url: https://crates.io/crates/pkcs5 +license(s): MIT +Copyright (c) 2021 The RustCrypto Project Developers + +crate: pkcs8 +version(s): 0.10.2 +url: https://crates.io/crates/pkcs8 +license(s): MIT +Copyright (c) 2020 The RustCrypto Project Developers + +crate: rand_core +version(s): 0.6.4 +url: https://crates.io/crates/rand_core +license(s): MIT +Copyright 2018 Developers of the Rand project +Copyright (c) 2014 The Rust Project Developers + +crate: ring +version(s): 0.17.14 +url: https://crates.io/crates/ring +license(s): Apache-2.0 AND ISC +No copyright statement was provided by the author even though they license may refer to it + +crate: rustls +version(s): 0.23.45 +url: https://crates.io/crates/rustls +license(s): MIT +Copyright (c) 2016 Joseph Birr-Pixton + +crate: rustls-pki-types +version(s): 1.14.0 +url: https://crates.io/crates/rustls-pki-types +license(s): MIT +Copyright (c) 2023 Dirkjan Ochtman + +crate: rustls-webpki +version(s): 0.103.15 +url: https://crates.io/crates/rustls-webpki +license(s): ISC +Copyright 2015 Brian Smith. + +crate: rx509 +version(s): 0.2.1 +url: https://crates.io/crates/rx509 +license(s): MIT +Copyright (c) Step Function I/O LLC + +crate: salsa20 +version(s): 0.10.2 +url: https://crates.io/crates/salsa20 +license(s): MIT +Copyright (c) 2019 Eric McCorkle + +crate: scopeguard +version(s): 1.2.0 +url: https://crates.io/crates/scopeguard +license(s): MIT +Copyright (c) 2016-2019 Ulrik Sverdrup "bluss" and scopeguard developers + +crate: scrypt +version(s): 0.11.0 +url: https://crates.io/crates/scrypt +license(s): MIT +Copyright (c) 2021 The RustCrypto Project Developers + +crate: scursor +version(s): 0.2.0 +url: https://crates.io/crates/scursor +license(s): MIT +Copyright (c) Step Function I/O LLC + +crate: serde +version(s): 1.0.228 +url: https://crates.io/crates/serde +license(s): MIT +No copyright statement was provided by the author even though they license may refer to it + +crate: serde_core +version(s): 1.0.228 +url: https://crates.io/crates/serde_core +license(s): MIT +No copyright statement was provided by the author even though they license may refer to it + +crate: serde_json +version(s): 1.0.149 +url: https://crates.io/crates/serde_json +license(s): MIT +No copyright statement was provided by the author even though they license may refer to it + +crate: serialport +version(s): 4.9.0 +url: https://crates.io/crates/serialport +license(s): MPL-2.0 + +crate: sfio-rustls-config +version(s): 0.4.0 +url: https://crates.io/crates/sfio-rustls-config +license(s): MIT +Copyright (c) Step Function I/O LLC + +crate: sha2 +version(s): 0.10.9 +url: https://crates.io/crates/sha2 +license(s): MIT +Copyright (c) 2006-2009 Graydon Hoare +Copyright (c) 2009-2013 Mozilla Foundation +Copyright (c) 2016 Artyom Pavlov + +crate: sharded-slab +version(s): 0.1.7 +url: https://crates.io/crates/sharded-slab +license(s): MIT +Copyright (c) 2019 Eliza Weisman + +crate: slab +version(s): 0.4.12 +url: https://crates.io/crates/slab +license(s): MIT +Copyright (c) 2019 Carl Lerche + +crate: smallvec +version(s): 1.15.1 +url: https://crates.io/crates/smallvec +license(s): MIT +Copyright (c) 2018 The Servo Project Developers + +crate: socket2 +version(s): 0.6.3 +url: https://crates.io/crates/socket2 +license(s): MIT +Copyright (c) 2014 Alex Crichton + +crate: spki +version(s): 0.7.3 +url: https://crates.io/crates/spki +license(s): MIT +Copyright (c) 2021-2022 The RustCrypto Project Developers + +crate: subtle +version(s): 2.6.1 +url: https://crates.io/crates/subtle +license(s): BSD-3-Clause +Copyright (c) 2016-2017 Isis Agora Lovecruft, Henry de Valence. All rights reserved. + +crate: thiserror +version(s): 2.0.18 +url: https://crates.io/crates/thiserror +license(s): MIT +No copyright statement was provided by the author even though they license may refer to it + +crate: thread_local +version(s): 1.1.9 +url: https://crates.io/crates/thread_local +license(s): MIT +Copyright (c) 2016 The Rust Project Developers + +crate: tokio +version(s): 1.52.1 +url: https://crates.io/crates/tokio +license(s): MIT +Copyright (c) 2022 Tokio Contributors + +crate: tokio-rustls +version(s): 0.26.4 +url: https://crates.io/crates/tokio-rustls +license(s): MIT +Copyright (c) 2019 Tokio Contributors + +crate: tokio-serial +version(s): 5.4.5 +url: https://crates.io/crates/tokio-serial +license(s): MIT +Copyright (c) 2017 Zac Berkowitz and other tokio-serial contributors. + +crate: tracing +version(s): 0.1.44 +url: https://crates.io/crates/tracing +license(s): MIT +Copyright (c) 2019 Tokio Contributors + +crate: tracing-core +version(s): 0.1.36 +url: https://crates.io/crates/tracing-core +license(s): MIT +Copyright (c) 2019 Tokio Contributors + +crate: tracing-log +version(s): 0.2.0 +url: https://crates.io/crates/tracing-log +license(s): MIT +Copyright (c) 2019 Tokio Contributors + +crate: tracing-serde +version(s): 0.2.0 +url: https://crates.io/crates/tracing-serde +license(s): MIT +Copyright (c) 2019 Tokio Contributors + +crate: tracing-subscriber +version(s): 0.3.23 +url: https://crates.io/crates/tracing-subscriber +license(s): MIT +Copyright (c) 2019 Tokio Contributors + +crate: typenum +version(s): 1.19.0 +url: https://crates.io/crates/typenum +license(s): MIT +Copyright (c) 2014 Paho Lurie-Gregg + +crate: unescaper +version(s): 0.1.8 +url: https://crates.io/crates/unescaper +license(s): MIT +Copyright (c) 2023 Hack Ink + +crate: untrusted +version(s): 0.9.0 +url: https://crates.io/crates/untrusted +license(s): ISC +Copyright 2015-2016 Brian Smith. + +crate: xxhash-rust +version(s): 0.8.15 +url: https://crates.io/crates/xxhash-rust +license(s): BSL-1.0 + +crate: zeroize +version(s): 1.8.2 +url: https://crates.io/crates/zeroize +license(s): MIT +Copyright (c) 2018-2021 The RustCrypto Project Developers + +crate: zmij +version(s): 1.0.21 +url: https://crates.io/crates/zmij +license(s): MIT +No copyright statement was provided by the author even though they license may refer to it + +============================== Apache-2.0 ===================================== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + + +================================= BSD-3-Clause ===================================== + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================= BSL-1.0 ===================================== + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +=============================== ISC =========================================== + +Permission to use, copy, modify, and /or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +================================= MIT ========================================= + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +================================= MPL-2.0 ===================================== + +1. Definitions + +-------------- + 1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. + 1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. + 1.3. "Contribution" means Covered Software of a particular Contributor. + 1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. + 1.5. "Incompatible With Secondary Licenses" means + (a) that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or + (b) that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. + 1.6. "Executable Form" means any form of the work other than Source Code Form. + 1.7. "Larger Work" means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. + 1.8. "License" means this document. + 1.9. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. + 1.10. "Modifications" means any of the following: + (a) any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or + (b) any new file in Source Code Form that contains any Covered Software. + 1.11. "Patent Claims" of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. + 1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. + 1.13. "Source Code Form" means the form of the work preferred for making modifications. + 1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. + +2. License Grants and Conditions + +-------------------------------- + 2.1. Grants + + Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: + (a) under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and + (b) under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. + 2.2. Effective Date + + The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. + 2.3. Limitations on Grant Scope + + The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: + (a) for any code that a Contributor has removed from Covered Software; or + (b) for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or + (c) under Patent Claims infringed by Covered Software in the absence of its Contributions. + + This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). + 2.4. Subsequent Licenses + + No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). + 2.5. Representation + + Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. + 2.6. Fair Use + + This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. + 2.7. Conditions + + Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. + +3. Responsibilities + +------------------- + 3.1. Distribution of Source Form + + All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. + 3.2. Distribution of Executable Form + + If You distribute Covered Software in Executable Form then: + (a) such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and + (b) You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. + 3.3. Distribution of a Larger Work + + You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). + 3.4. Notices + + You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. + 3.5. Application of Additional Terms + + You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. + +4. Inability to Comply Due to Statute or Regulation + +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. + +5. Termination + +-------------- + 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. + 5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. + 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. + +************************************************************************ + +6. Disclaimer of Warranty + +* ------------------------- * + +Covered Software is provided under this License on an "as is" basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Covered Software is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Covered Software is with You. Should any Covered Software prove defective in any respect, You (not any Contributor) assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of any Covered Software is authorized under this License except under this disclaimer. + +************************************************************************ + +************************************************************************ + +7. Limitation of Liability + +* -------------------------- * + +Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall any Contributor, or anyone who distributes Covered Software as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability shall not apply to liability for death or personal injury resulting from such party's negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You. + +************************************************************************ + +8. Litigation + +------------- + +Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. + +9. Miscellaneous + +---------------- + +This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. + +10. Versions of the License + +--------------------------- + 10.1. New Versions + + Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. + 10.2. Effect of New Versions + + You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. + 10.3. Modified Versions + + If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). + 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + + If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice + +------------------------------------------- + +This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice + +--------------------------------------------------------- + +This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. + + From d0e381bbc8b0406713cb163ea0cd251bd61752e3 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 14:13:51 -0700 Subject: [PATCH 08/12] README migration notice; license renderer returns io::Result - README: notice that 0.3.0 removed the cargo-cyclonedx commands, with the 0.2.1 pin for consumers that have not migrated - README: say explicitly that Cargo's SBOM precursor files are a future input reader for this tool; approval and outputs stay the same - licenses::write only performs writes, so it returns std::io::Result --- README.md | 11 +++++++++-- allow-list/src/commands.rs | 2 +- allow-list/src/licenses.rs | 5 +---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 259302d..cf62ade 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,11 @@ never decides scope or roles. ## Commands +0.3.0 removed `gen-licenses` / `gen-licenses-dir`, which read `cargo cyclonedx` SBOMs: +those describe cargo-cyclonedx's own feature selection, not the product's build. Produce the +build evidence above and use the `*-log` commands; until you migrate, pin +`cargo install --git https://github.com/stepfunc/bom-tools.git --tag 0.2.1`. + ```sh # one target allow-list gen-licenses-log -g build.json --tree tree.txt --runtime-tree runtime-tree.txt \ @@ -132,5 +137,7 @@ Supported builds: `cargo build` of a library or binary (`cargo check`, tests, ex benches are rejected), crates.io and workspace packages. Not supported: build-script overrides, `-Zbuild-std`, and non-Rust components inside `-sys` crates beyond the crate's declared license. -When Cargo's SBOM precursor files (`-Z sbom`) are stable they will replace the build log and -`cargo tree` inputs ([#8](https://github.com/stepfunc/bom-tools/issues/8)). +When Cargo's SBOM precursor files (`-Z sbom`) are stable, `allow-list` will read them as its +build evidence instead of the build log and `cargo tree` outputs +([#8](https://github.com/stepfunc/bom-tools/issues/8)). The approval rules, the license report +and the SBOM stay the same; only the input reader changes. diff --git a/allow-list/src/commands.rs b/allow-list/src/commands.rs index ebf545b..a228a73 100644 --- a/allow-list/src/commands.rs +++ b/allow-list/src/commands.rs @@ -32,7 +32,7 @@ pub(crate) fn gen_licenses(evidence: &Evidence, w: W) -> Result<(), an let config: Config = load_json(&evidence.config)?; let metadata: Metadata = load_json(&evidence.metadata)?; let validated = validate(evidence, &metadata, &config)?; - licenses::write(&validated, w) + Ok(licenses::write(&validated, w)?) } /// Options of the SBOM commands diff --git a/allow-list/src/licenses.rs b/allow-list/src/licenses.rs index f8a5464..b507cf5 100644 --- a/allow-list/src/licenses.rs +++ b/allow-list/src/licenses.rs @@ -6,10 +6,7 @@ use std::collections::BTreeMap; use std::io::Write; /// Write the license report of a validated inventory -pub(crate) fn write( - validated: &ValidatedInventory, - mut w: W, -) -> Result<(), anyhow::Error> { +pub(crate) fn write(validated: &ValidatedInventory, mut w: W) -> std::io::Result<()> { let shipped = validated.shipped_third_party(); // every license that applies, once, with its text appended at the end From be8d54ea178af5371b8984621497b7bfbeafe10b Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 14:15:49 -0700 Subject: [PATCH 09/12] Rename to bom-tools; two commands: licenses and sbom The tool produces the license report and the SBOM from build evidence and enforces the allow list, so name it after the repository it lives in. - crate, binary and directory: allow-list -> bom-tools - `licenses` and `sbom` replace gen-licenses-log[-dir] and gen-sbom-log[-dir]; both read a directory of targets (-e/--evidence-dir), so a single target is one subdirectory - README, CHANGELOG (with a migration section) and CI updated --- .github/workflows/ci.yml | 4 +- CHANGELOG.md | 34 ++--- Cargo.lock | 32 ++-- Cargo.toml | 2 +- README.md | 31 ++-- allow-list/src/cli.rs | 138 ------------------ {allow-list => bom-tools}/Cargo.lock | 0 {allow-list => bom-tools}/Cargo.toml | 2 +- .../licenses/apache2.txt | 0 {allow-list => bom-tools}/licenses/bsd3.txt | 0 {allow-list => bom-tools}/licenses/bsl.txt | 0 {allow-list => bom-tools}/licenses/isc.txt | 0 {allow-list => bom-tools}/licenses/mit.txt | 0 {allow-list => bom-tools}/licenses/mpl2.txt | 0 .../licenses/openssl.txt | 0 .../licenses/unicode_dfs_2016.txt | 0 {allow-list => bom-tools}/src/approval.rs | 0 bom-tools/src/cli.rs | 77 ++++++++++ {allow-list => bom-tools}/src/commands.rs | 0 {allow-list => bom-tools}/src/config.rs | 0 .../src/fixture_tests.rs | 5 +- {allow-list => bom-tools}/src/golden_tests.rs | 0 {allow-list => bom-tools}/src/graph.rs | 0 .../src/input/build_log.rs | 0 .../src/input/cargo_tree.rs | 0 {allow-list => bom-tools}/src/input/mod.rs | 0 {allow-list => bom-tools}/src/input/pkgid.rs | 0 {allow-list => bom-tools}/src/inventory.rs | 0 {allow-list => bom-tools}/src/licenses.rs | 0 {allow-list => bom-tools}/src/main.rs | 18 +-- {allow-list => bom-tools}/src/sbom.rs | 0 .../tests/fixtures/dnp3/Cargo.lock | 0 .../tests/fixtures/dnp3/allowed.json | 0 .../tests/fixtures/dnp3/expected-licenses.txt | 0 .../tests/fixtures/dnp3/metadata.json | 0 .../fixtures/dnp3/targets/aws/build.json | 0 .../dnp3/targets/aws/runtime-tree.txt | 0 .../tests/fixtures/dnp3/targets/aws/tree.txt | 0 .../fixtures/dnp3/targets/ring/build.json | 0 .../dnp3/targets/ring/runtime-tree.txt | 0 .../tests/fixtures/dnp3/targets/ring/tree.txt | 0 .../tests/fixtures/workspace/Cargo.lock | 0 .../tests/fixtures/workspace/Cargo.toml | 2 +- .../workspace/alias-target/Cargo.toml | 0 .../workspace/alias-target/src/lib.rs | 0 .../tests/fixtures/workspace/app/Cargo.toml | 0 .../tests/fixtures/workspace/app/build.rs | 0 .../tests/fixtures/workspace/app/src/lib.rs | 0 .../fixtures/workspace/common/Cargo.toml | 0 .../fixtures/workspace/common/src/lib.rs | 0 .../fixtures/workspace/hostextra/Cargo.toml | 0 .../fixtures/workspace/hostextra/src/lib.rs | 0 .../fixtures/workspace/optdep/Cargo.toml | 0 .../fixtures/workspace/optdep/src/lib.rs | 0 .../tests/fixtures/workspace/pm/Cargo.toml | 0 .../tests/fixtures/workspace/pm/src/lib.rs | 0 .../fixtures/workspace/pmonly/Cargo.toml | 0 .../fixtures/workspace/pmonly/src/lib.rs | 0 .../fixtures/workspace/shared/Cargo.toml | 0 .../fixtures/workspace/shared/src/lib.rs | 0 .../tests/fixtures/workspace/tool/Cargo.toml | 0 .../tests/fixtures/workspace/tool/src/lib.rs | 0 .../fixtures/workspace/unixonly/Cargo.toml | 0 .../fixtures/workspace/unixonly/src/lib.rs | 0 .../fixtures/workspace/winonly/Cargo.toml | 0 .../fixtures/workspace/winonly/src/lib.rs | 0 66 files changed, 134 insertions(+), 211 deletions(-) delete mode 100644 allow-list/src/cli.rs rename {allow-list => bom-tools}/Cargo.lock (100%) rename {allow-list => bom-tools}/Cargo.toml (95%) rename {allow-list => bom-tools}/licenses/apache2.txt (100%) rename {allow-list => bom-tools}/licenses/bsd3.txt (100%) rename {allow-list => bom-tools}/licenses/bsl.txt (100%) rename {allow-list => bom-tools}/licenses/isc.txt (100%) rename {allow-list => bom-tools}/licenses/mit.txt (100%) rename {allow-list => bom-tools}/licenses/mpl2.txt (100%) rename {allow-list => bom-tools}/licenses/openssl.txt (100%) rename {allow-list => bom-tools}/licenses/unicode_dfs_2016.txt (100%) rename {allow-list => bom-tools}/src/approval.rs (100%) create mode 100644 bom-tools/src/cli.rs rename {allow-list => bom-tools}/src/commands.rs (100%) rename {allow-list => bom-tools}/src/config.rs (100%) rename {allow-list => bom-tools}/src/fixture_tests.rs (98%) rename {allow-list => bom-tools}/src/golden_tests.rs (100%) rename {allow-list => bom-tools}/src/graph.rs (100%) rename {allow-list => bom-tools}/src/input/build_log.rs (100%) rename {allow-list => bom-tools}/src/input/cargo_tree.rs (100%) rename {allow-list => bom-tools}/src/input/mod.rs (100%) rename {allow-list => bom-tools}/src/input/pkgid.rs (100%) rename {allow-list => bom-tools}/src/inventory.rs (100%) rename {allow-list => bom-tools}/src/licenses.rs (100%) rename {allow-list => bom-tools}/src/main.rs (58%) rename {allow-list => bom-tools}/src/sbom.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/dnp3/Cargo.lock (100%) rename {allow-list => bom-tools}/tests/fixtures/dnp3/allowed.json (100%) rename {allow-list => bom-tools}/tests/fixtures/dnp3/expected-licenses.txt (100%) rename {allow-list => bom-tools}/tests/fixtures/dnp3/metadata.json (100%) rename {allow-list => bom-tools}/tests/fixtures/dnp3/targets/aws/build.json (100%) rename {allow-list => bom-tools}/tests/fixtures/dnp3/targets/aws/runtime-tree.txt (100%) rename {allow-list => bom-tools}/tests/fixtures/dnp3/targets/aws/tree.txt (100%) rename {allow-list => bom-tools}/tests/fixtures/dnp3/targets/ring/build.json (100%) rename {allow-list => bom-tools}/tests/fixtures/dnp3/targets/ring/runtime-tree.txt (100%) rename {allow-list => bom-tools}/tests/fixtures/dnp3/targets/ring/tree.txt (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/Cargo.lock (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/Cargo.toml (77%) rename {allow-list => bom-tools}/tests/fixtures/workspace/alias-target/Cargo.toml (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/alias-target/src/lib.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/app/Cargo.toml (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/app/build.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/app/src/lib.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/common/Cargo.toml (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/common/src/lib.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/hostextra/Cargo.toml (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/hostextra/src/lib.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/optdep/Cargo.toml (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/optdep/src/lib.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/pm/Cargo.toml (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/pm/src/lib.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/pmonly/Cargo.toml (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/pmonly/src/lib.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/shared/Cargo.toml (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/shared/src/lib.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/tool/Cargo.toml (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/tool/src/lib.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/unixonly/Cargo.toml (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/unixonly/src/lib.rs (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/winonly/Cargo.toml (100%) rename {allow-list => bom-tools}/tests/fixtures/workspace/winonly/src/lib.rs (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c197c68..e5fb988 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,6 @@ jobs: curl -sSLo cyclonedx https://github.com/CycloneDX/cyclonedx-cli/releases/download/$CYCLONEDX_CLI_VERSION/cyclonedx-linux-x64 echo "$CYCLONEDX_CLI_SHA256 cyclonedx" | sha256sum -c chmod +x cyclonedx - F=allow-list/tests/fixtures/dnp3 - cargo run -- gen-sbom-log-dir -l $F/targets --root-package dnp3-ffi -m $F/metadata.json -c $F/allowed.json --lockfile $F/Cargo.lock > sbom.json + F=bom-tools/tests/fixtures/dnp3 + cargo run -- sbom -e $F/targets --root-package dnp3-ffi -m $F/metadata.json -c $F/allowed.json --lockfile $F/Cargo.lock > sbom.json ./cyclonedx validate --input-file sbom.json --input-version v1_5 --fail-on-errors diff --git a/CHANGELOG.md b/CHANGELOG.md index 3087c65..f2097aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,22 @@ # Changelog -Notable changes to the `allow-list` tool, newest first. Version numbers mark -CLI releases (so a consumer can pin a specific build, e.g. `cargo install --tag`); +Notable changes to `bom-tools` (named `allow-list` before 0.3.0), newest first. Version +numbers mark CLI releases (so a consumer can pin a specific build, e.g. `cargo install --tag`); they are not a library API compatibility promise. ## [0.3.0] - 2026-10-09 -Breaking: the cargo-cyclonedx commands are removed, and `gen-licenses-log` / -`gen-licenses-log-dir` take new inputs and arguments and their output changes (see below). -See the README for how to produce the inputs. Consumers that install from `main` without a -tag should pin `--tag 0.2.1` until they migrate. +Breaking: the executable is renamed, the commands are replaced, and the license report's +scope changes (see below). See the README for how to produce the inputs. Consumers that +install from `main` without a tag should pin `--tag 0.2.1` until they migrate. ### Added -- `gen-sbom-log` and `gen-sbom-log-dir`: a CycloneDX 1.5 JSON SBOM from the same validated - inventory as the license report. Runtime packages have `scope: required`, build-time - packages `scope: excluded`; licenses are the declared SPDX expressions (commercial license - for first-party and vendor packages); `--lockfile` adds SHA-256 hashes; dependencies are - the observed package edges; `--omit-serial-number` with `SOURCE_DATE_EPOCH` gives - reproducible output. +- `sbom`: a CycloneDX 1.5 JSON SBOM from the same validated inventory as the license report. + Runtime packages have `scope: required`, build-time packages `scope: excluded`; licenses are + the declared SPDX expressions (commercial license for first-party and vendor packages); + `--lockfile` adds SHA-256 hashes; dependencies are the observed package edges; + `--omit-serial-number` with `SOURCE_DATE_EPOCH` gives reproducible output. - Every compiled package is classified as runtime or build-time by `cargo tree` (Cargo's own resolver), cross-checked against the build log: packages and (package, features) variants must match exactly. Build logs are validated (successful `build-finished`, no test, example @@ -32,12 +30,12 @@ tag should pin `--tag 0.2.1` until they migrate. ### Changed -- `gen-licenses-log` / `gen-licenses-log-dir` require `--root-package` and the two - `cargo tree` outputs per target (`--tree`, `--runtime-tree`, and `--log` for `-g`; fixed names - `build.json`, `tree.txt`, `runtime-tree.txt` in each target directory for the `-dir` - variant, which no longer takes `--log-file`). `cargo metadata` should be generated with - `--all-features`. -- Their report now lists only packages linked into the product: build-time packages +- The executable and crate are renamed from `allow-list` to `bom-tools`. +- `gen-licenses-log` / `gen-licenses-log-dir` are replaced by `licenses`, which reads a + directory with one subdirectory per target (`-e/--evidence-dir`), each holding + `build.json`, `tree.txt` and `runtime-tree.txt`, and requires `--root-package`. + `cargo metadata` should be generated with `--all-features`. +- The license report now lists only packages linked into the product: build-time packages (proc-macros and their dependencies, build-script dependencies) are no longer listed, and first-party crates are matched by name and version instead of being skipped. diff --git a/Cargo.lock b/Cargo.lock index 00435f7..695ed98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,22 +11,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "allow-list" -version = "0.3.0" -dependencies = [ - "anyhow", - "cargo_metadata", - "clap", - "cyclonedx-bom", - "semver", - "serde", - "serde_json", - "spdx", - "time", - "toml", -] - [[package]] name = "anstream" version = "0.6.18" @@ -107,6 +91,22 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +[[package]] +name = "bom-tools" +version = "0.3.0" +dependencies = [ + "anyhow", + "cargo_metadata", + "clap", + "cyclonedx-bom", + "semver", + "serde", + "serde_json", + "spdx", + "time", + "toml", +] + [[package]] name = "camino" version = "1.2.4" diff --git a/Cargo.toml b/Cargo.toml index 88cb38d..db3a9ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ resolver = "2" members = [ - "allow-list", + "bom-tools", ] [workspace.lints.rust] diff --git a/README.md b/README.md index cf62ade..59dca5b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # bom-tools -`allow-list` produces the third-party license report (`third-party-licenses.txt`) and a +`bom-tools` produces the third-party license report (`third-party-licenses.txt`) and a CycloneDX 1.5 SBOM for a Rust product, from the evidence of the build that produced it, and -checks every dependency against a reviewed allow-list (`allowed.json`). +checks every dependency against a reviewed allow list (`allowed.json`). ```sh cargo install --git https://github.com/stepfunc/bom-tools.git --tag 0.3.0 @@ -58,29 +58,30 @@ never decides scope or roles. ## Commands -0.3.0 removed `gen-licenses` / `gen-licenses-dir`, which read `cargo cyclonedx` SBOMs: -those describe cargo-cyclonedx's own feature selection, not the product's build. Produce the -build evidence above and use the `*-log` commands; until you migrate, pin -`cargo install --git https://github.com/stepfunc/bom-tools.git --tag 0.2.1`. +Both commands read a directory with one subdirectory per target (holding `build.json`, +`tree.txt` and `runtime-tree.txt`); a single target is a directory with one subdirectory. ```sh -# one target -allow-list gen-licenses-log -g build.json --tree tree.txt --runtime-tree runtime-tree.txt \ - --root-package dnp3-ffi -m metadata.json -c allowed.json > third-party-licenses.txt - -# every target, one subdirectory each (build.json, tree.txt, runtime-tree.txt) -allow-list gen-licenses-log-dir -l evidence --root-package dnp3-ffi -m metadata.json -c allowed.json \ +bom-tools licenses -e evidence --root-package dnp3-ffi -m metadata.json -c allowed.json \ > third-party-licenses.txt -allow-list gen-sbom-log-dir -l evidence --root-package dnp3-ffi -m metadata.json -c allowed.json \ +bom-tools sbom -e evidence --root-package dnp3-ffi -m metadata.json -c allowed.json \ --lockfile Cargo.lock > dnp3-ffi-1.7.0.cdx.json ``` -`gen-sbom-log` / `gen-sbom-log-dir` take the same inputs plus: +`sbom` also takes: - `--lockfile `: add each crates.io package's SHA-256 (the `.crate` archive hash); - `--omit-serial-number`: with `SOURCE_DATE_EPOCH` (used as the timestamp), output is byte-for-byte reproducible. +### Migrating from 0.2 + +0.3.0 renamed the executable from `allow-list` to `bom-tools`, replaced `gen-licenses-log*` +with `licenses` and `sbom`, and removed `gen-licenses` / `gen-licenses-dir`, which read +`cargo cyclonedx` SBOMs: those describe cargo-cyclonedx's own feature selection, not the +product's build. Until you migrate, pin +`cargo install --git https://github.com/stepfunc/bom-tools.git --tag 0.2.1`. + ## `allowed.json` ```jsonc @@ -137,7 +138,7 @@ Supported builds: `cargo build` of a library or binary (`cargo check`, tests, ex benches are rejected), crates.io and workspace packages. Not supported: build-script overrides, `-Zbuild-std`, and non-Rust components inside `-sys` crates beyond the crate's declared license. -When Cargo's SBOM precursor files (`-Z sbom`) are stable, `allow-list` will read them as its +When Cargo's SBOM precursor files (`-Z sbom`) are stable, `bom-tools` will read them as its build evidence instead of the build log and `cargo tree` outputs ([#8](https://github.com/stepfunc/bom-tools/issues/8)). The approval rules, the license report and the SBOM stay the same; only the input reader changes. diff --git a/allow-list/src/cli.rs b/allow-list/src/cli.rs deleted file mode 100644 index 2949bef..0000000 --- a/allow-list/src/cli.rs +++ /dev/null @@ -1,138 +0,0 @@ -use crate::commands::{Evidence, SbomOptions}; -use crate::input::{target_dirs, TargetInput}; -use clap::{Args, Parser, Subcommand}; -use std::path::PathBuf; - -#[derive(Parser)] -#[clap(author, version, about, long_about = None)] -#[clap(propagate_version = true)] -pub(crate) struct Cli { - #[clap(subcommand)] - pub(crate) command: Commands, -} - -// variant names are the CLI subcommand names, so they keep their common `Gen` prefix -#[allow(clippy::enum_variant_names)] -#[derive(Subcommand)] -pub(crate) enum Commands { - /// outputs a human-readable report of the 3rd party licenses that ship in the product, - /// from the build evidence of one target - GenLicensesLog { - #[clap(flatten)] - target: TargetFiles, - #[clap(flatten)] - common: Common, - }, - /// outputs a human-readable report of the 3rd party licenses that ship in the product, - /// from the build evidence of every target in the subdirectories of a directory - GenLicensesLogDir { - #[clap(flatten)] - targets: TargetDir, - #[clap(flatten)] - common: Common, - }, - /// outputs a CycloneDX 1.5 JSON SBOM of the product, from the build evidence of one target - GenSbomLog { - #[clap(flatten)] - target: TargetFiles, - #[clap(flatten)] - common: Common, - #[clap(flatten)] - sbom: SbomArgs, - }, - /// outputs a CycloneDX 1.5 JSON SBOM of the product, from the build evidence of every - /// target in the subdirectories of a directory - GenSbomLogDir { - #[clap(flatten)] - targets: TargetDir, - #[clap(flatten)] - common: Common, - #[clap(flatten)] - sbom: SbomArgs, - }, -} - -/// Options of the SBOM commands -#[derive(Args)] -pub(crate) struct SbomArgs { - /// path to the `Cargo.lock`, to add SHA-256 hashes of crates.io packages - #[clap(value_parser, long)] - lockfile: Option, - /// omit the random serial number, for reproducible output (with `SOURCE_DATE_EPOCH`) - #[clap(long)] - omit_serial_number: bool, -} - -impl From for SbomOptions { - fn from(args: SbomArgs) -> Self { - Self { - lockfile: args.lockfile, - omit_serial_number: args.omit_serial_number, - } - } -} - -/// The build evidence of one target -#[derive(Args)] -pub(crate) struct TargetFiles { - /// path to the `cargo build --message-format json` log - #[clap(value_parser, long, short = 'g', alias = "log-path")] - log: PathBuf, - /// path to the `cargo tree -e normal,build --prefix depth --format '{p}|{f}'` output - #[clap(value_parser, long)] - tree: PathBuf, - /// path to the `cargo tree -e normal,no-proc-macro --prefix depth --format '{p}|{f}'` output - #[clap(value_parser, long)] - runtime_tree: PathBuf, -} - -/// The build evidence of several targets -#[derive(Args)] -pub(crate) struct TargetDir { - /// directory with one subdirectory per target, each containing `build.json`, `tree.txt` - /// and `runtime-tree.txt` - #[clap(value_parser, long, short = 'l')] - list_dir: PathBuf, -} - -/// Arguments shared by every command that reads build evidence -#[derive(Args)] -pub(crate) struct Common { - /// name of the workspace package that is the product (e.g. `dnp3-ffi`) - #[clap(long)] - root_package: String, - /// path to `cargo metadata --format-version 1 --all-features` JSON output - #[clap(value_parser, long, short = 'm')] - metadata_path: PathBuf, - /// path to the JSON configuration (allow-list) - #[clap(value_parser, long, short = 'c')] - config_path: PathBuf, -} - -impl TargetFiles { - pub(crate) fn evidence(self, common: Common) -> Evidence { - let target = TargetInput::LogAndTree { - log: self.log, - tree: self.tree, - runtime_tree: self.runtime_tree, - }; - common.evidence(vec![target]) - } -} - -impl TargetDir { - pub(crate) fn evidence(self, common: Common) -> Result { - Ok(common.evidence(target_dirs(&self.list_dir)?)) - } -} - -impl Common { - fn evidence(self, targets: Vec) -> Evidence { - Evidence { - targets, - root_package: self.root_package, - metadata: self.metadata_path, - config: self.config_path, - } - } -} diff --git a/allow-list/Cargo.lock b/bom-tools/Cargo.lock similarity index 100% rename from allow-list/Cargo.lock rename to bom-tools/Cargo.lock diff --git a/allow-list/Cargo.toml b/bom-tools/Cargo.toml similarity index 95% rename from allow-list/Cargo.toml rename to bom-tools/Cargo.toml index 64fa7ba..f67aaf4 100644 --- a/allow-list/Cargo.toml +++ b/bom-tools/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "allow-list" +name = "bom-tools" version = "0.3.0" edition = "2021" diff --git a/allow-list/licenses/apache2.txt b/bom-tools/licenses/apache2.txt similarity index 100% rename from allow-list/licenses/apache2.txt rename to bom-tools/licenses/apache2.txt diff --git a/allow-list/licenses/bsd3.txt b/bom-tools/licenses/bsd3.txt similarity index 100% rename from allow-list/licenses/bsd3.txt rename to bom-tools/licenses/bsd3.txt diff --git a/allow-list/licenses/bsl.txt b/bom-tools/licenses/bsl.txt similarity index 100% rename from allow-list/licenses/bsl.txt rename to bom-tools/licenses/bsl.txt diff --git a/allow-list/licenses/isc.txt b/bom-tools/licenses/isc.txt similarity index 100% rename from allow-list/licenses/isc.txt rename to bom-tools/licenses/isc.txt diff --git a/allow-list/licenses/mit.txt b/bom-tools/licenses/mit.txt similarity index 100% rename from allow-list/licenses/mit.txt rename to bom-tools/licenses/mit.txt diff --git a/allow-list/licenses/mpl2.txt b/bom-tools/licenses/mpl2.txt similarity index 100% rename from allow-list/licenses/mpl2.txt rename to bom-tools/licenses/mpl2.txt diff --git a/allow-list/licenses/openssl.txt b/bom-tools/licenses/openssl.txt similarity index 100% rename from allow-list/licenses/openssl.txt rename to bom-tools/licenses/openssl.txt diff --git a/allow-list/licenses/unicode_dfs_2016.txt b/bom-tools/licenses/unicode_dfs_2016.txt similarity index 100% rename from allow-list/licenses/unicode_dfs_2016.txt rename to bom-tools/licenses/unicode_dfs_2016.txt diff --git a/allow-list/src/approval.rs b/bom-tools/src/approval.rs similarity index 100% rename from allow-list/src/approval.rs rename to bom-tools/src/approval.rs diff --git a/bom-tools/src/cli.rs b/bom-tools/src/cli.rs new file mode 100644 index 0000000..ece066e --- /dev/null +++ b/bom-tools/src/cli.rs @@ -0,0 +1,77 @@ +use crate::commands::{Evidence, SbomOptions}; +use crate::input::target_dirs; +use clap::{Args, Parser, Subcommand}; +use std::path::PathBuf; + +#[derive(Parser)] +#[clap(author, version, about, long_about = None)] +#[clap(propagate_version = true)] +pub(crate) struct Cli { + #[clap(subcommand)] + pub(crate) command: Commands, +} + +#[derive(Subcommand)] +pub(crate) enum Commands { + /// outputs a human-readable report of the 3rd party licenses that ship in the product + Licenses { + #[clap(flatten)] + evidence: EvidenceArgs, + }, + /// outputs a CycloneDX 1.5 JSON SBOM of the product + Sbom { + #[clap(flatten)] + evidence: EvidenceArgs, + #[clap(flatten)] + sbom: SbomArgs, + }, +} + +/// Arguments shared by every command +#[derive(Args)] +pub(crate) struct EvidenceArgs { + /// directory with one subdirectory per target the product is built for, each containing + /// `build.json`, `tree.txt` and `runtime-tree.txt` + #[clap(value_parser, long, short = 'e')] + evidence_dir: PathBuf, + /// name of the workspace package that is the product (e.g. `dnp3-ffi`) + #[clap(long)] + root_package: String, + /// path to `cargo metadata --format-version 1 --all-features` JSON output + #[clap(value_parser, long, short = 'm')] + metadata_path: PathBuf, + /// path to the JSON configuration (the allow list, e.g. `allowed.json`) + #[clap(value_parser, long, short = 'c')] + config_path: PathBuf, +} + +impl EvidenceArgs { + pub(crate) fn evidence(self) -> Result { + Ok(Evidence { + targets: target_dirs(&self.evidence_dir)?, + root_package: self.root_package, + metadata: self.metadata_path, + config: self.config_path, + }) + } +} + +/// Options of the SBOM command +#[derive(Args)] +pub(crate) struct SbomArgs { + /// path to the `Cargo.lock`, to add SHA-256 hashes of crates.io packages + #[clap(value_parser, long)] + lockfile: Option, + /// omit the random serial number, for reproducible output (with `SOURCE_DATE_EPOCH`) + #[clap(long)] + omit_serial_number: bool, +} + +impl From for SbomOptions { + fn from(args: SbomArgs) -> Self { + Self { + lockfile: args.lockfile, + omit_serial_number: args.omit_serial_number, + } + } +} diff --git a/allow-list/src/commands.rs b/bom-tools/src/commands.rs similarity index 100% rename from allow-list/src/commands.rs rename to bom-tools/src/commands.rs diff --git a/allow-list/src/config.rs b/bom-tools/src/config.rs similarity index 100% rename from allow-list/src/config.rs rename to bom-tools/src/config.rs diff --git a/allow-list/src/fixture_tests.rs b/bom-tools/src/fixture_tests.rs similarity index 98% rename from allow-list/src/fixture_tests.rs rename to bom-tools/src/fixture_tests.rs index ef6eb04..7fbfe63 100644 --- a/allow-list/src/fixture_tests.rs +++ b/bom-tools/src/fixture_tests.rs @@ -31,10 +31,7 @@ fn evidence() -> &'static Evidence { .unwrap() .parent() .unwrap() - .join(format!( - "allow-list-fixture-evidence-{}", - std::process::id() - )); + .join(format!("bom-tools-fixture-evidence-{}", std::process::id())); let _ = std::fs::remove_dir_all(&dir); std::fs::create_dir_all(&dir).unwrap(); let host = host_triple(); diff --git a/allow-list/src/golden_tests.rs b/bom-tools/src/golden_tests.rs similarity index 100% rename from allow-list/src/golden_tests.rs rename to bom-tools/src/golden_tests.rs diff --git a/allow-list/src/graph.rs b/bom-tools/src/graph.rs similarity index 100% rename from allow-list/src/graph.rs rename to bom-tools/src/graph.rs diff --git a/allow-list/src/input/build_log.rs b/bom-tools/src/input/build_log.rs similarity index 100% rename from allow-list/src/input/build_log.rs rename to bom-tools/src/input/build_log.rs diff --git a/allow-list/src/input/cargo_tree.rs b/bom-tools/src/input/cargo_tree.rs similarity index 100% rename from allow-list/src/input/cargo_tree.rs rename to bom-tools/src/input/cargo_tree.rs diff --git a/allow-list/src/input/mod.rs b/bom-tools/src/input/mod.rs similarity index 100% rename from allow-list/src/input/mod.rs rename to bom-tools/src/input/mod.rs diff --git a/allow-list/src/input/pkgid.rs b/bom-tools/src/input/pkgid.rs similarity index 100% rename from allow-list/src/input/pkgid.rs rename to bom-tools/src/input/pkgid.rs diff --git a/allow-list/src/inventory.rs b/bom-tools/src/inventory.rs similarity index 100% rename from allow-list/src/inventory.rs rename to bom-tools/src/inventory.rs diff --git a/allow-list/src/licenses.rs b/bom-tools/src/licenses.rs similarity index 100% rename from allow-list/src/licenses.rs rename to bom-tools/src/licenses.rs diff --git a/allow-list/src/main.rs b/bom-tools/src/main.rs similarity index 58% rename from allow-list/src/main.rs rename to bom-tools/src/main.rs index 49a43d8..62c7dfa 100644 --- a/allow-list/src/main.rs +++ b/bom-tools/src/main.rs @@ -29,21 +29,9 @@ fn main() -> Result<(), anyhow::Error> { let cli = Cli::parse(); match cli.command { - Commands::GenLicensesLog { target, common } => { - commands::gen_licenses(&target.evidence(common), stdout()) + Commands::Licenses { evidence } => commands::gen_licenses(&evidence.evidence()?, stdout()), + Commands::Sbom { evidence, sbom } => { + commands::gen_sbom(&evidence.evidence()?, &sbom.into(), stdout()) } - Commands::GenLicensesLogDir { targets, common } => { - commands::gen_licenses(&targets.evidence(common)?, stdout()) - } - Commands::GenSbomLog { - target, - common, - sbom, - } => commands::gen_sbom(&target.evidence(common), &sbom.into(), stdout()), - Commands::GenSbomLogDir { - targets, - common, - sbom, - } => commands::gen_sbom(&targets.evidence(common)?, &sbom.into(), stdout()), } } diff --git a/allow-list/src/sbom.rs b/bom-tools/src/sbom.rs similarity index 100% rename from allow-list/src/sbom.rs rename to bom-tools/src/sbom.rs diff --git a/allow-list/tests/fixtures/dnp3/Cargo.lock b/bom-tools/tests/fixtures/dnp3/Cargo.lock similarity index 100% rename from allow-list/tests/fixtures/dnp3/Cargo.lock rename to bom-tools/tests/fixtures/dnp3/Cargo.lock diff --git a/allow-list/tests/fixtures/dnp3/allowed.json b/bom-tools/tests/fixtures/dnp3/allowed.json similarity index 100% rename from allow-list/tests/fixtures/dnp3/allowed.json rename to bom-tools/tests/fixtures/dnp3/allowed.json diff --git a/allow-list/tests/fixtures/dnp3/expected-licenses.txt b/bom-tools/tests/fixtures/dnp3/expected-licenses.txt similarity index 100% rename from allow-list/tests/fixtures/dnp3/expected-licenses.txt rename to bom-tools/tests/fixtures/dnp3/expected-licenses.txt diff --git a/allow-list/tests/fixtures/dnp3/metadata.json b/bom-tools/tests/fixtures/dnp3/metadata.json similarity index 100% rename from allow-list/tests/fixtures/dnp3/metadata.json rename to bom-tools/tests/fixtures/dnp3/metadata.json diff --git a/allow-list/tests/fixtures/dnp3/targets/aws/build.json b/bom-tools/tests/fixtures/dnp3/targets/aws/build.json similarity index 100% rename from allow-list/tests/fixtures/dnp3/targets/aws/build.json rename to bom-tools/tests/fixtures/dnp3/targets/aws/build.json diff --git a/allow-list/tests/fixtures/dnp3/targets/aws/runtime-tree.txt b/bom-tools/tests/fixtures/dnp3/targets/aws/runtime-tree.txt similarity index 100% rename from allow-list/tests/fixtures/dnp3/targets/aws/runtime-tree.txt rename to bom-tools/tests/fixtures/dnp3/targets/aws/runtime-tree.txt diff --git a/allow-list/tests/fixtures/dnp3/targets/aws/tree.txt b/bom-tools/tests/fixtures/dnp3/targets/aws/tree.txt similarity index 100% rename from allow-list/tests/fixtures/dnp3/targets/aws/tree.txt rename to bom-tools/tests/fixtures/dnp3/targets/aws/tree.txt diff --git a/allow-list/tests/fixtures/dnp3/targets/ring/build.json b/bom-tools/tests/fixtures/dnp3/targets/ring/build.json similarity index 100% rename from allow-list/tests/fixtures/dnp3/targets/ring/build.json rename to bom-tools/tests/fixtures/dnp3/targets/ring/build.json diff --git a/allow-list/tests/fixtures/dnp3/targets/ring/runtime-tree.txt b/bom-tools/tests/fixtures/dnp3/targets/ring/runtime-tree.txt similarity index 100% rename from allow-list/tests/fixtures/dnp3/targets/ring/runtime-tree.txt rename to bom-tools/tests/fixtures/dnp3/targets/ring/runtime-tree.txt diff --git a/allow-list/tests/fixtures/dnp3/targets/ring/tree.txt b/bom-tools/tests/fixtures/dnp3/targets/ring/tree.txt similarity index 100% rename from allow-list/tests/fixtures/dnp3/targets/ring/tree.txt rename to bom-tools/tests/fixtures/dnp3/targets/ring/tree.txt diff --git a/allow-list/tests/fixtures/workspace/Cargo.lock b/bom-tools/tests/fixtures/workspace/Cargo.lock similarity index 100% rename from allow-list/tests/fixtures/workspace/Cargo.lock rename to bom-tools/tests/fixtures/workspace/Cargo.lock diff --git a/allow-list/tests/fixtures/workspace/Cargo.toml b/bom-tools/tests/fixtures/workspace/Cargo.toml similarity index 77% rename from allow-list/tests/fixtures/workspace/Cargo.toml rename to bom-tools/tests/fixtures/workspace/Cargo.toml index 175ac8f..a503e8a 100644 --- a/allow-list/tests/fixtures/workspace/Cargo.toml +++ b/bom-tools/tests/fixtures/workspace/Cargo.toml @@ -1,5 +1,5 @@ # A small workspace exercising the cases the build-log + cargo tree reader must classify; -# built for real by the tests in `allow-list/src/fixture_tests.rs`. +# built for real by the tests in `bom-tools/src/fixture_tests.rs`. [workspace] resolver = "2" members = ["app", "shared", "hostextra", "common", "pm", "pmonly", "tool", "alias-target", "optdep", "winonly", "unixonly"] diff --git a/allow-list/tests/fixtures/workspace/alias-target/Cargo.toml b/bom-tools/tests/fixtures/workspace/alias-target/Cargo.toml similarity index 100% rename from allow-list/tests/fixtures/workspace/alias-target/Cargo.toml rename to bom-tools/tests/fixtures/workspace/alias-target/Cargo.toml diff --git a/allow-list/tests/fixtures/workspace/alias-target/src/lib.rs b/bom-tools/tests/fixtures/workspace/alias-target/src/lib.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/alias-target/src/lib.rs rename to bom-tools/tests/fixtures/workspace/alias-target/src/lib.rs diff --git a/allow-list/tests/fixtures/workspace/app/Cargo.toml b/bom-tools/tests/fixtures/workspace/app/Cargo.toml similarity index 100% rename from allow-list/tests/fixtures/workspace/app/Cargo.toml rename to bom-tools/tests/fixtures/workspace/app/Cargo.toml diff --git a/allow-list/tests/fixtures/workspace/app/build.rs b/bom-tools/tests/fixtures/workspace/app/build.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/app/build.rs rename to bom-tools/tests/fixtures/workspace/app/build.rs diff --git a/allow-list/tests/fixtures/workspace/app/src/lib.rs b/bom-tools/tests/fixtures/workspace/app/src/lib.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/app/src/lib.rs rename to bom-tools/tests/fixtures/workspace/app/src/lib.rs diff --git a/allow-list/tests/fixtures/workspace/common/Cargo.toml b/bom-tools/tests/fixtures/workspace/common/Cargo.toml similarity index 100% rename from allow-list/tests/fixtures/workspace/common/Cargo.toml rename to bom-tools/tests/fixtures/workspace/common/Cargo.toml diff --git a/allow-list/tests/fixtures/workspace/common/src/lib.rs b/bom-tools/tests/fixtures/workspace/common/src/lib.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/common/src/lib.rs rename to bom-tools/tests/fixtures/workspace/common/src/lib.rs diff --git a/allow-list/tests/fixtures/workspace/hostextra/Cargo.toml b/bom-tools/tests/fixtures/workspace/hostextra/Cargo.toml similarity index 100% rename from allow-list/tests/fixtures/workspace/hostextra/Cargo.toml rename to bom-tools/tests/fixtures/workspace/hostextra/Cargo.toml diff --git a/allow-list/tests/fixtures/workspace/hostextra/src/lib.rs b/bom-tools/tests/fixtures/workspace/hostextra/src/lib.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/hostextra/src/lib.rs rename to bom-tools/tests/fixtures/workspace/hostextra/src/lib.rs diff --git a/allow-list/tests/fixtures/workspace/optdep/Cargo.toml b/bom-tools/tests/fixtures/workspace/optdep/Cargo.toml similarity index 100% rename from allow-list/tests/fixtures/workspace/optdep/Cargo.toml rename to bom-tools/tests/fixtures/workspace/optdep/Cargo.toml diff --git a/allow-list/tests/fixtures/workspace/optdep/src/lib.rs b/bom-tools/tests/fixtures/workspace/optdep/src/lib.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/optdep/src/lib.rs rename to bom-tools/tests/fixtures/workspace/optdep/src/lib.rs diff --git a/allow-list/tests/fixtures/workspace/pm/Cargo.toml b/bom-tools/tests/fixtures/workspace/pm/Cargo.toml similarity index 100% rename from allow-list/tests/fixtures/workspace/pm/Cargo.toml rename to bom-tools/tests/fixtures/workspace/pm/Cargo.toml diff --git a/allow-list/tests/fixtures/workspace/pm/src/lib.rs b/bom-tools/tests/fixtures/workspace/pm/src/lib.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/pm/src/lib.rs rename to bom-tools/tests/fixtures/workspace/pm/src/lib.rs diff --git a/allow-list/tests/fixtures/workspace/pmonly/Cargo.toml b/bom-tools/tests/fixtures/workspace/pmonly/Cargo.toml similarity index 100% rename from allow-list/tests/fixtures/workspace/pmonly/Cargo.toml rename to bom-tools/tests/fixtures/workspace/pmonly/Cargo.toml diff --git a/allow-list/tests/fixtures/workspace/pmonly/src/lib.rs b/bom-tools/tests/fixtures/workspace/pmonly/src/lib.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/pmonly/src/lib.rs rename to bom-tools/tests/fixtures/workspace/pmonly/src/lib.rs diff --git a/allow-list/tests/fixtures/workspace/shared/Cargo.toml b/bom-tools/tests/fixtures/workspace/shared/Cargo.toml similarity index 100% rename from allow-list/tests/fixtures/workspace/shared/Cargo.toml rename to bom-tools/tests/fixtures/workspace/shared/Cargo.toml diff --git a/allow-list/tests/fixtures/workspace/shared/src/lib.rs b/bom-tools/tests/fixtures/workspace/shared/src/lib.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/shared/src/lib.rs rename to bom-tools/tests/fixtures/workspace/shared/src/lib.rs diff --git a/allow-list/tests/fixtures/workspace/tool/Cargo.toml b/bom-tools/tests/fixtures/workspace/tool/Cargo.toml similarity index 100% rename from allow-list/tests/fixtures/workspace/tool/Cargo.toml rename to bom-tools/tests/fixtures/workspace/tool/Cargo.toml diff --git a/allow-list/tests/fixtures/workspace/tool/src/lib.rs b/bom-tools/tests/fixtures/workspace/tool/src/lib.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/tool/src/lib.rs rename to bom-tools/tests/fixtures/workspace/tool/src/lib.rs diff --git a/allow-list/tests/fixtures/workspace/unixonly/Cargo.toml b/bom-tools/tests/fixtures/workspace/unixonly/Cargo.toml similarity index 100% rename from allow-list/tests/fixtures/workspace/unixonly/Cargo.toml rename to bom-tools/tests/fixtures/workspace/unixonly/Cargo.toml diff --git a/allow-list/tests/fixtures/workspace/unixonly/src/lib.rs b/bom-tools/tests/fixtures/workspace/unixonly/src/lib.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/unixonly/src/lib.rs rename to bom-tools/tests/fixtures/workspace/unixonly/src/lib.rs diff --git a/allow-list/tests/fixtures/workspace/winonly/Cargo.toml b/bom-tools/tests/fixtures/workspace/winonly/Cargo.toml similarity index 100% rename from allow-list/tests/fixtures/workspace/winonly/Cargo.toml rename to bom-tools/tests/fixtures/workspace/winonly/Cargo.toml diff --git a/allow-list/tests/fixtures/workspace/winonly/src/lib.rs b/bom-tools/tests/fixtures/workspace/winonly/src/lib.rs similarity index 100% rename from allow-list/tests/fixtures/workspace/winonly/src/lib.rs rename to bom-tools/tests/fixtures/workspace/winonly/src/lib.rs From 4faaa21205c4d83199806ce5247fade2c38d20b6 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 14:18:32 -0700 Subject: [PATCH 10/12] README and doc wording after the rename --- README.md | 4 ++-- bom-tools/src/commands.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 59dca5b..02d09a2 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ bom-tools sbom -e evidence --root-package dnp3-ffi -m metadata.json -c allowed.j ### Migrating from 0.2 0.3.0 renamed the executable from `allow-list` to `bom-tools`, replaced `gen-licenses-log*` -with `licenses` and `sbom`, and removed `gen-licenses` / `gen-licenses-dir`, which read +with `licenses`, added `sbom`, and removed `gen-licenses` / `gen-licenses-dir`, which read `cargo cyclonedx` SBOMs: those describe cargo-cyclonedx's own feature selection, not the product's build. Until you migrate, pin `cargo install --git https://github.com/stepfunc/bom-tools.git --tag 0.2.1`. @@ -113,7 +113,7 @@ our own code and need no entry; the root package must be one. declared SPDX `license`, and the reviewed licenses must satisfy it (reviewed `MIT` satisfies `MIT OR Apache-2.0` but not `MIT AND Apache-2.0`). -`commercial_license` is required by the SBOM commands. `embedded: true` marks a build-time dependency whose own code ships anyway (for example a build +`commercial_license` is required by the `sbom` command. `embedded: true` marks a build-time dependency whose own code ships anyway (for example a build script that copies source it provides into the product); it is treated as runtime, its dependencies are not. License names: `MIT`, `ISC`, `BSD3` (with `copyright`), `Apache2`, `OpenSSL`, `BSLv1`, `MPLv2`, `UnicodeDFS2016`. diff --git a/bom-tools/src/commands.rs b/bom-tools/src/commands.rs index a228a73..467a6fc 100644 --- a/bom-tools/src/commands.rs +++ b/bom-tools/src/commands.rs @@ -35,7 +35,7 @@ pub(crate) fn gen_licenses(evidence: &Evidence, w: W) -> Result<(), an Ok(licenses::write(&validated, w)?) } -/// Options of the SBOM commands +/// Options of the SBOM command pub(crate) struct SbomOptions { /// `Cargo.lock` from which to take SHA-256 hashes of crates.io packages pub(crate) lockfile: Option, From 6a75b691fca3f184473099937d4a381eba040eed Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 14:23:17 -0700 Subject: [PATCH 11/12] Require --lockfile for sbom so every crates.io component has its SHA-256 --- CHANGELOG.md | 3 +- README.md | 3 +- bom-tools/src/cli.rs | 4 +-- bom-tools/src/commands.rs | 18 +++++----- bom-tools/src/golden_tests.rs | 6 ++-- bom-tools/src/sbom.rs | 62 ++++++++++++++++++++--------------- 6 files changed, 52 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2097aa..6d978d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,8 @@ install from `main` without a tag should pin `--tag 0.2.1` until they migrate. - `sbom`: a CycloneDX 1.5 JSON SBOM from the same validated inventory as the license report. Runtime packages have `scope: required`, build-time packages `scope: excluded`; licenses are the declared SPDX expressions (commercial license for first-party and vendor packages); - `--lockfile` adds SHA-256 hashes; dependencies are the observed package edges; + the required `--lockfile` (the build's `Cargo.lock`) supplies every crates.io package's + SHA-256; dependencies are the observed package edges; `--omit-serial-number` with `SOURCE_DATE_EPOCH` gives reproducible output. - Every compiled package is classified as runtime or build-time by `cargo tree` (Cargo's own resolver), cross-checked against the build log: packages and (package, features) variants diff --git a/README.md b/README.md index 02d09a2..5cd72ac 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,8 @@ bom-tools sbom -e evidence --root-package dnp3-ffi -m metadata.json -c allowed.j `sbom` also takes: -- `--lockfile `: add each crates.io package's SHA-256 (the `.crate` archive hash); +- `--lockfile ` (required): the build's lockfile, for each crates.io package's + SHA-256 (the `.crate` archive hash Cargo verified when downloading it); - `--omit-serial-number`: with `SOURCE_DATE_EPOCH` (used as the timestamp), output is byte-for-byte reproducible. diff --git a/bom-tools/src/cli.rs b/bom-tools/src/cli.rs index ece066e..6afb5b3 100644 --- a/bom-tools/src/cli.rs +++ b/bom-tools/src/cli.rs @@ -59,9 +59,9 @@ impl EvidenceArgs { /// Options of the SBOM command #[derive(Args)] pub(crate) struct SbomArgs { - /// path to the `Cargo.lock`, to add SHA-256 hashes of crates.io packages + /// path to the build's `Cargo.lock`, for the SHA-256 hashes of crates.io packages #[clap(value_parser, long)] - lockfile: Option, + lockfile: PathBuf, /// omit the random serial number, for reproducible output (with `SOURCE_DATE_EPOCH`) #[clap(long)] omit_serial_number: bool, diff --git a/bom-tools/src/commands.rs b/bom-tools/src/commands.rs index 467a6fc..fcbf9dd 100644 --- a/bom-tools/src/commands.rs +++ b/bom-tools/src/commands.rs @@ -37,8 +37,8 @@ pub(crate) fn gen_licenses(evidence: &Evidence, w: W) -> Result<(), an /// Options of the SBOM command pub(crate) struct SbomOptions { - /// `Cargo.lock` from which to take SHA-256 hashes of crates.io packages - pub(crate) lockfile: Option, + /// The build's `Cargo.lock`, for the SHA-256 hashes of crates.io packages + pub(crate) lockfile: PathBuf, /// Omit the random serial number, for reproducible output pub(crate) omit_serial_number: bool, } @@ -52,15 +52,13 @@ pub(crate) fn gen_sbom( let config: Config = load_json(&evidence.config)?; let metadata: Metadata = load_json(&evidence.metadata)?; let validated = validate(evidence, &metadata, &config)?; - let checksums = match &options.lockfile { - Some(path) => Some( - Checksums::from_lockfile(&std::fs::read_to_string(path)?) - .with_context(|| format!("parsing {}", path.display()))?, - ), - None => None, - }; + let lockfile = &options.lockfile; + let checksums = std::fs::read_to_string(lockfile) + .map_err(anyhow::Error::from) + .and_then(|text| Checksums::from_lockfile(&text)) + .with_context(|| format!("reading {}", lockfile.display()))?; let options = sbom::Options { - checksums: checksums.as_ref(), + checksums: &checksums, omit_serial_number: options.omit_serial_number, timestamp: timestamp()?, }; diff --git a/bom-tools/src/golden_tests.rs b/bom-tools/src/golden_tests.rs index 294f4d3..6ebf4b3 100644 --- a/bom-tools/src/golden_tests.rs +++ b/bom-tools/src/golden_tests.rs @@ -330,7 +330,7 @@ fn sbom_bytes() -> Vec { let checksums = Checksums::from_lockfile(&std::fs::read_to_string(fixture("Cargo.lock")).unwrap()).unwrap(); let options = sbom::Options { - checksums: Some(&checksums), + checksums: &checksums, omit_serial_number: true, timestamp: DateTime::try_from("2025-10-09T08:53:20Z".to_string()).unwrap(), }; @@ -461,9 +461,7 @@ fn sbom_command_uses_the_given_lockfile() { // a lockfile without crates.io checksums (the path-only fixture workspace's) must be // rejected, which proves the command passes `--lockfile` through to the renderer let options = SbomOptions { - lockfile: Some( - Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/workspace/Cargo.lock"), - ), + lockfile: Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/workspace/Cargo.lock"), omit_serial_number: false, }; let err = commands::gen_sbom(&all_targets(), &options, &mut Vec::new()).unwrap_err(); diff --git a/bom-tools/src/sbom.rs b/bom-tools/src/sbom.rs index 9c796bd..ed529d4 100644 --- a/bom-tools/src/sbom.rs +++ b/bom-tools/src/sbom.rs @@ -66,8 +66,8 @@ impl Checksums { /// How to produce the document pub(crate) struct Options<'a> { - /// Add SHA-256 hashes of crates.io packages from this lockfile - pub(crate) checksums: Option<&'a Checksums>, + /// SHA-256 hashes of crates.io packages, from the build's lockfile + pub(crate) checksums: &'a Checksums, /// Omit the random serial number, for reproducible output pub(crate) omit_serial_number: bool, /// The document's creation time @@ -147,8 +147,8 @@ pub(crate) fn write( )])); } // only crates.io packages reach here besides first-party ones (see `inventory`) - if let (Some(checksums), false) = (options.checksums, approved.component.first_party) { - let checksum = checksums.get(package).ok_or_else(|| { + if !approved.component.first_party { + let checksum = options.checksums.get(package).ok_or_else(|| { anyhow!( "the lockfile has no checksum for {} {}", package.name, @@ -259,17 +259,27 @@ mod tests { .collect() } - /// Render the SBOM of `app` with the given dependencies, all directly under the root + /// Render the SBOM of `app` with the given dependencies, all directly under the root, and a + /// lockfile entry (hash `HASH_A`) for each crates.io dependency fn render( deps: &[(PackageKey, Option<&str>, Role)], - checksums: Option<&Checksums>, ) -> Result { - render_with(deps, checksums, &config()) + let entries: Vec<(&str, String, &str)> = deps + .iter() + .filter(|(k, _, _)| k.source == crate::graph::SourceKind::CratesIo) + .map(|(k, _, _)| (k.name.as_str(), k.version.to_string(), HASH_A)) + .collect(); + let entries: Vec<(&str, &str, &str)> = entries + .iter() + .map(|(n, v, h)| (*n, v.as_str(), *h)) + .collect(); + let checksums = Checksums::from_lockfile(&lockfile(&entries)).unwrap(); + render_with(deps, &checksums, &config()) } fn render_with( deps: &[(PackageKey, Option<&str>, Role)], - checksums: Option<&Checksums>, + checksums: &Checksums, config: &Config, ) -> Result { let (meta, graph) = app_with(deps); @@ -305,14 +315,11 @@ mod tests { #[test] fn encodes_scope_license_and_references_per_approval() { - let bom = render( - &[ - (key("serde", "1.0.0"), Some("MIT/Apache-2.0"), Role::Runtime), - (key("cc", "1.0.0"), None, Role::BuildTime), - (key("sfio", "1.0.0"), None, Role::Runtime), - ], - None, - ) + let bom = render(&[ + (key("serde", "1.0.0"), Some("MIT/Apache-2.0"), Role::Runtime), + (key("cc", "1.0.0"), None, Role::BuildTime), + (key("sfio", "1.0.0"), None, Role::Runtime), + ]) .unwrap(); let serde = component(&bom, "serde", "1.0.0"); assert_eq!(serde["scope"], "required"); @@ -351,12 +358,13 @@ mod tests { ("serde", "2.0.0", HASH_B), ])) .unwrap(); - let bom = render( + let bom = render_with( &[ (key("serde", "1.0.0"), Some("MIT"), Role::Runtime), (key("serde", "2.0.0"), Some("MIT"), Role::Runtime), ], - Some(&checksums), + &checksums, + &config(), ) .unwrap(); assert_eq!( @@ -384,13 +392,10 @@ mod tests { #[test] fn rejects_colliding_references() { // a workspace member and a crates.io package with the same name and version - let err = render( - &[ - (path_key("serde", "1.0.0"), None, Role::Runtime), - (key("serde", "1.0.0"), Some("MIT"), Role::Runtime), - ], - None, - ) + let err = render(&[ + (path_key("serde", "1.0.0"), None, Role::Runtime), + (key("serde", "1.0.0"), Some("MIT"), Role::Runtime), + ]) .unwrap_err(); assert!(err.to_string().contains("share the reference"), "{err}"); } @@ -400,7 +405,12 @@ mod tests { let mut config = config(); config.commercial_license = None; let deps = [(key("serde", "1.0.0"), Some("MIT"), Role::Runtime)]; - let err = render_with(&deps, None, &config).unwrap_err(); + let err = render_with( + &deps, + &Checksums::from_lockfile(&lockfile(&[("serde", "1.0.0", HASH_A)])).unwrap(), + &config, + ) + .unwrap_err(); assert!(err.to_string().contains("commercial_license"), "{err}"); } } From 47c7b9ace5b3bd582dcdeaa74a0cd18c49adaef9 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 9 Oct 2026 14:29:40 -0700 Subject: [PATCH 12/12] Test that the sbom command takes hashes from the given lockfile --- bom-tools/src/golden_tests.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/bom-tools/src/golden_tests.rs b/bom-tools/src/golden_tests.rs index 6ebf4b3..85a5d33 100644 --- a/bom-tools/src/golden_tests.rs +++ b/bom-tools/src/golden_tests.rs @@ -458,8 +458,28 @@ fn sbom_is_reproducible() { #[test] fn sbom_command_uses_the_given_lockfile() { - // a lockfile without crates.io checksums (the path-only fixture workspace's) must be - // rejected, which proves the command passes `--lockfile` through to the renderer + // the command takes every hash from the lockfile it is given + let options = SbomOptions { + lockfile: fixture("Cargo.lock"), + omit_serial_number: false, + }; + let mut out = Vec::new(); + commands::gen_sbom(&all_targets(), &options, &mut out).unwrap(); + let bom: serde_json::Value = serde_json::from_slice(&out).unwrap(); + let serde = bom["components"] + .as_array() + .unwrap() + .iter() + .find(|c| c["name"] == "serde") + .unwrap(); + let lock = std::fs::read_to_string(fixture("Cargo.lock")).unwrap(); + let hash = serde["hashes"][0]["content"].as_str().unwrap(); + assert!(lock.contains(&format!( + "name = \"serde\"\nversion = \"{}\"\nsource = \"registry+https://github.com/rust-lang/crates.io-index\"\nchecksum = \"{hash}\"", + serde["version"].as_str().unwrap() + ))); + + // and a lockfile without crates.io checksums (the path-only fixture workspace's) fails let options = SbomOptions { lockfile: Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/workspace/Cargo.lock"), omit_serial_number: false,