From 5b20a2a049083a457f1e71ce0f7b737dd19910b5 Mon Sep 17 00:00:00 2001 From: Thomas Marchand Date: Wed, 25 Feb 2026 17:52:02 +0000 Subject: [PATCH 1/9] fix(core): align export contract with desktop verifier, augment replay witness with singleton (#176) The generator's `isFullyVerifiable` flag required replay-capable simulation witness inputs even for full (non-witness-only) simulations, causing a "partial" badge in the generator while the desktop correctly showed "Fully Verified". Now replay inputs only gate the flag for witness-only packages. Also ensures replay witness accounts include the Safe proxy's slot 0 (singleton pointer) and the singleton contract itself so local EVM replay can execute the DELEGATECALL chain correctly. Removes em dashes from all .ts/.tsx files for consistent punctuation. --- .../src-tauri/src/simulation_replay.rs | 97 ++++++++ apps/desktop/src/lib/network-support.ts | 2 +- apps/desktop/src/lib/safety-checks.tsx | 2 +- apps/desktop/src/screens/VerifyScreen.tsx | 8 +- apps/generator/app/page.tsx | 17 +- packages/core/scripts/test-replay-witness.ts | 123 ++++++++++ packages/core/src/lib/consensus/beacon-api.ts | 2 +- .../src/lib/package/__tests__/creator.test.ts | 217 +++++++++++++++++- packages/core/src/lib/package/creator.ts | 14 +- packages/core/src/lib/safe/api.ts | 2 +- packages/core/src/lib/safe/signatures.ts | 2 +- packages/core/src/lib/settings/store.ts | 2 +- .../lib/simulation/__tests__/summary.test.ts | 4 +- packages/core/src/lib/simulation/fetcher.ts | 133 ++++++++++- .../core/src/lib/simulation/slot-decoder.ts | 4 +- packages/core/src/lib/simulation/summary.ts | 6 +- packages/core/src/lib/types.ts | 2 +- 17 files changed, 589 insertions(+), 48 deletions(-) create mode 100644 packages/core/scripts/test-replay-witness.ts diff --git a/apps/desktop/src-tauri/src/simulation_replay.rs b/apps/desktop/src-tauri/src/simulation_replay.rs index c4f653a3..2ce391ca 100644 --- a/apps/desktop/src-tauri/src/simulation_replay.rs +++ b/apps/desktop/src-tauri/src/simulation_replay.rs @@ -1440,6 +1440,103 @@ mod tests { assert_eq!(result.reason, REASON_REPLAY_MATCHED); } + #[test] + fn proxy_delegatecall_fails_without_slot0_and_singleton() { + // Actual GnosisSafeProxy bytecode: reads slot 0 for singleton, then + // DELEGATECALLs. Without slot 0, it delegates to address(0) → 0x return. + let proxy_code = "0x608060405273ffffffffffffffffffffffffffffffffffffffff600054167fa619486e0000000000000000000000000000000000000000000000000000000060003514156050578060005260206000f35b3660008037600080366000845af43d6000803e60008114156070573d6000fd5b3d6000f3fe"; + // Minimal singleton: returns abi.encode(true) for any call + let singleton_code = "0x600160005260206000f3"; + + let caller = "0x1000000000000000000000000000000000000001"; + let proxy_addr = "0x2000000000000000000000000000000000000002"; + let singleton_addr = "0x3000000000000000000000000000000000000003"; + let expected_return = "0x0000000000000000000000000000000000000000000000000000000000000001"; + + // Without slot 0 → proxy delegates to address(0) → empty return → mismatch + let result_without = verify_simulation_replay(SimulationReplayInput { + chain_id: 100, + safe_address: caller.to_string(), + transaction: ReplayTransaction { + to: proxy_addr.to_string(), + value: "0".to_string(), + data: Some("0xdeadbeef".to_string()), + operation: 0, + safe_tx_gas: Some("500000".to_string()), + }, + simulation: ReplaySimulation { + success: true, + return_data: Some(expected_return.to_string()), + gas_used: "500000".to_string(), + block_number: 1, + logs: Vec::new(), + }, + simulation_witness: ReplayWitness { + replay_block: Some(replay_block("1")), + replay_accounts: Some(vec![ + caller_account(caller), + target_account(proxy_addr, proxy_code), + ]), + replay_caller: Some(caller.to_string()), + replay_gas_limit: Some(500000), + witness_only: Some(true), + }, + }); + assert!(result_without.executed); + assert!(!result_without.success); + assert_eq!(result_without.reason, REASON_REPLAY_MISMATCH_RETURN_DATA); + + // With slot 0 + singleton → correct delegatecall → match + let mut proxy_storage = BTreeMap::new(); + proxy_storage.insert( + "0x0000000000000000000000000000000000000000000000000000000000000000" + .to_string(), + format!( + "0x000000000000000000000000{}", + &singleton_addr[2..] + ), + ); + + let result_with = verify_simulation_replay(SimulationReplayInput { + chain_id: 100, + safe_address: caller.to_string(), + transaction: ReplayTransaction { + to: proxy_addr.to_string(), + value: "0".to_string(), + data: Some("0xdeadbeef".to_string()), + operation: 0, + safe_tx_gas: Some("500000".to_string()), + }, + simulation: ReplaySimulation { + success: true, + return_data: Some(expected_return.to_string()), + gas_used: "500000".to_string(), + block_number: 1, + logs: Vec::new(), + }, + simulation_witness: ReplayWitness { + replay_block: Some(replay_block("1")), + replay_accounts: Some(vec![ + caller_account(caller), + ReplayWitnessAccount { + address: proxy_addr.to_string(), + balance: "0".to_string(), + nonce: 0, + code: proxy_code.to_string(), + storage: proxy_storage, + }, + target_account(singleton_addr, singleton_code), + ]), + replay_caller: Some(caller.to_string()), + replay_gas_limit: Some(500000), + witness_only: Some(true), + }, + }); + assert!(result_with.executed); + assert!(result_with.success, "{result_with:?}"); + assert_eq!(result_with.reason, REASON_REPLAY_MATCHED); + } + #[test] fn e2e_replay_from_payload_file_when_configured() { let Ok(path) = env::var("SAFELENS_E2E_REPLAY_INPUT") else { diff --git a/apps/desktop/src/lib/network-support.ts b/apps/desktop/src/lib/network-support.ts index 09230749..b77613a4 100644 --- a/apps/desktop/src/lib/network-support.ts +++ b/apps/desktop/src/lib/network-support.ts @@ -107,7 +107,7 @@ export function buildNetworkSupportStatus( ); } - // Policy proof is required for full verification — without it, the + // Policy proof is required for full verification -- without it, the // desktop verifier cannot confirm the on-chain Safe state independently. if (!hasOnchainPolicyProof) { return partial( diff --git a/apps/desktop/src/lib/safety-checks.tsx b/apps/desktop/src/lib/safety-checks.tsx index 912cdf3b..12f309fe 100644 --- a/apps/desktop/src/lib/safety-checks.tsx +++ b/apps/desktop/src/lib/safety-checks.tsx @@ -94,7 +94,7 @@ const CONSENSUS_ERROR_DETAILS: Record = { "invalid-expected-state-root": "Expected state root format is invalid.", "missing-policy-state-root": - "Consensus proof is present but cannot be cross-verified — no on-chain policy proof was included. Regenerate with an RPC URL for full verification.", + "Consensus proof is present but cannot be cross-verified. No on-chain policy proof was included. Regenerate with an RPC URL for full verification.", }; function isConsensusFailureDetailCode( diff --git a/apps/desktop/src/screens/VerifyScreen.tsx b/apps/desktop/src/screens/VerifyScreen.tsx index 159d416c..727cb5e5 100644 --- a/apps/desktop/src/screens/VerifyScreen.tsx +++ b/apps/desktop/src/screens/VerifyScreen.tsx @@ -573,7 +573,7 @@ function SafePolicySection({ evidence }: { evidence: EvidencePackage }) { {/* Modules warning */} {hasModules && (
-
Modules enabled — can bypass signatures
+
Modules enabled - can bypass signatures
{policy.modules.map((mod) => (
@@ -754,7 +754,7 @@ function ExecutionSafetyPanel({ status: "error" as const, } : hasWarning && allDataAbsent - ? { label: "Skipped", description: "Generated without an RPC URL — some verification data is unavailable.", status: "skipped" as const } + ? { label: "Skipped", description: "Generated without an RPC URL. Some verification data is unavailable.", status: "skipped" as const } : hasWarning || replayPending || signaturesPending || signaturesUnsupported ? { label: "Partially Verified", @@ -1066,7 +1066,7 @@ function ExecutionSafetyPanel({
{stateDiffSummary.silentContracts > 0 && (
- {stateDiffSummary.silentContracts} contract{stateDiffSummary.silentContracts !== 1 ? "s" : ""} modified storage without emitting events — review state diffs for hidden effects. + {stateDiffSummary.silentContracts} contract{stateDiffSummary.silentContracts !== 1 ? "s" : ""} modified storage without emitting events. Review state diffs for hidden effects.
)}
@@ -1111,7 +1111,7 @@ function ExecutionSafetyPanel({
) : (
- Simulation not available — {getSimulationUnavailableReason(evidence).toLowerCase()} + Simulation not available: {getSimulationUnavailableReason(evidence).toLowerCase()}
)} diff --git a/apps/generator/app/page.tsx b/apps/generator/app/page.tsx index e6002928..b4362ec6 100644 --- a/apps/generator/app/page.tsx +++ b/apps/generator/app/page.tsx @@ -106,14 +106,7 @@ function EvidenceDisplay({ }) { const [showDetails, setShowDetails] = useState(false); const isFullyVerifiable = evidence.exportContract?.mode === "fully-verifiable"; - const displayExportReasons = - evidence.exportContract?.reasons.filter((reason) => { - if (reason !== "missing-simulation-witness") return true; - // Only surface this when the package is explicitly witness-only. - // Otherwise simulation effects are still included and desktop can - // validate execution without requiring replay-derived effects. - return evidence.simulationWitness?.witnessOnly === true; - }) ?? []; + const displayExportReasons = evidence.exportContract?.reasons ?? []; // Decode simulation events (memoized to avoid recomputation on re-render) const nativeSymbol = DEFAULT_SETTINGS_CONFIG.chains?.[String(evidence.chainId)]?.nativeTokenSymbol ?? "ETH"; @@ -161,10 +154,10 @@ function EvidenceDisplay({
{displayExportReasons.length > 0 ? ( displayExportReasons.map((reason) => ( -
· {getExportContractReasonLabel(reason)}
+
{getExportContractReasonLabel(reason)}
)) ) : ( -
· This package has partial verification coverage for this environment.
+
This package has partial verification coverage for this environment.
)}
)} @@ -270,7 +263,7 @@ function EvidenceDisplay({
{stateDiffSummary.silentContracts > 0 && (
- {stateDiffSummary.silentContracts} contract{stateDiffSummary.silentContracts !== 1 ? "s" : ""} modified storage without emitting events — review state diffs for hidden effects. + {stateDiffSummary.silentContracts} contract{stateDiffSummary.silentContracts !== 1 ? "s" : ""} modified storage without emitting events. Review state diffs for hidden effects.
)}
@@ -351,7 +344,7 @@ function EvidenceDisplay({
{hasModules && (
- Modules — can bypass signatures + Modules - can bypass signatures
{policy.modules.map((mod) => (
diff --git a/packages/core/scripts/test-replay-witness.ts b/packages/core/scripts/test-replay-witness.ts new file mode 100644 index 00000000..dea61f5a --- /dev/null +++ b/packages/core/scripts/test-replay-witness.ts @@ -0,0 +1,123 @@ +/** + * Generate a replay input JSON for the Gnosis Chain transaction, + * then verify it can be deserialized by checking key fields. + * + * Usage: + * bun run scripts/test-replay-witness.ts + * + * To feed into Rust e2e test: + * SAFELENS_E2E_REPLAY_INPUT=/tmp/replay-input.json cargo test e2e_replay -- --ignored + */ + +import { createPublicClient, http, pad, toHex, type Address, type Hex } from "viem"; +import { gnosis } from "viem/chains"; +import { fetchSimulation, fetchSimulationWitness } from "../src/lib/simulation/fetcher"; +import { slotToKey, SLOT_SINGLETON } from "../src/lib/proof/safe-layout"; +import { writeFileSync } from "node:fs"; + +const SAFE_ADDRESS = "0xba260842B007FaB4119C9747D709119DE4257276" as Address; +const CHAIN_ID = 100; +const RPC_URL = "https://rpc.gnosischain.com"; + +const transaction = { + to: "0x5bb21B30E912871D27182E7b7F9C37C888269cb2", + value: "1000000000000000000", + data: null, + operation: 0 as const, + nonce: 1, + safeTxGas: "0", + baseGas: "0", + gasPrice: "0", + gasToken: "0x0000000000000000000000000000000000000000", + refundReceiver: "0x0000000000000000000000000000000000000000", +}; + +async function main() { + console.log("Fetching simulation..."); + const simulation = await fetchSimulation(SAFE_ADDRESS, CHAIN_ID, transaction, { + rpcUrl: RPC_URL, + }); + console.log(` success=${simulation.success} returnData=${simulation.returnData} gasUsed=${simulation.gasUsed}`); + console.log(` blockNumber=${simulation.blockNumber} traceAvailable=${simulation.traceAvailable}`); + + console.log("\nFetching simulation witness..."); + const witness = await fetchSimulationWitness( + SAFE_ADDRESS, + CHAIN_ID, + transaction, + simulation, + { rpcUrl: RPC_URL } + ); + + // Verify the fix: check that slot 0 and the singleton are present + const safeAccount = witness.replayAccounts?.find( + (a) => a.address.toLowerCase() === SAFE_ADDRESS.toLowerCase() + ); + + const slot0Key = slotToKey(SLOT_SINGLETON); + const slot0Value = safeAccount?.storage[slot0Key]; + console.log(`\n Safe replay account found: ${!!safeAccount}`); + console.log(` Slot 0 (singleton) present: ${!!slot0Value}`); + console.log(` Slot 0 value: ${slot0Value}`); + + if (slot0Value) { + const singletonAddr = ("0x" + slot0Value.slice(26)).toLowerCase(); + console.log(` Singleton address: ${singletonAddr}`); + + const hasSingleton = witness.replayAccounts?.some( + (a) => a.address.toLowerCase() === singletonAddr + ); + console.log(` Singleton in replay accounts: ${hasSingleton}`); + + if (hasSingleton) { + const singletonAccount = witness.replayAccounts?.find( + (a) => a.address.toLowerCase() === singletonAddr + ); + console.log(` Singleton code length: ${singletonAccount?.code.length ?? 0} chars`); + } + } + + console.log(`\n Total replay accounts: ${witness.replayAccounts?.length ?? 0}`); + for (const account of witness.replayAccounts ?? []) { + const storageCount = Object.keys(account.storage).length; + console.log(` ${account.address}: code=${account.code.length > 4 ? "yes" : "no"} storage=${storageCount} slots`); + } + + // Build the replay input JSON for the Rust e2e test + const replayInput = { + chainId: CHAIN_ID, + safeAddress: SAFE_ADDRESS, + transaction: { + to: transaction.to, + value: transaction.value, + data: transaction.data ?? "0x", + operation: transaction.operation, + safeTxGas: transaction.safeTxGas, + }, + simulation: { + success: simulation.success, + returnData: simulation.returnData, + gasUsed: simulation.gasUsed, + blockNumber: simulation.blockNumber, + logs: simulation.logs, + }, + simulationWitness: { + replayBlock: witness.replayBlock, + replayAccounts: witness.replayAccounts, + replayCaller: witness.replayCaller, + replayGasLimit: witness.replayGasLimit, + witnessOnly: true, + }, + }; + + const outPath = "/tmp/safelens-replay-input.json"; + writeFileSync(outPath, JSON.stringify(replayInput, null, 2)); + console.log(`\nWrote replay input to ${outPath}`); + console.log("Run Rust e2e test with:"); + console.log(` cd apps/desktop/src-tauri && SAFELENS_E2E_REPLAY_INPUT=${outPath} cargo test e2e_replay -- --ignored --nocapture`); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/packages/core/src/lib/consensus/beacon-api.ts b/packages/core/src/lib/consensus/beacon-api.ts index 8c78317d..b6ec731e 100644 --- a/packages/core/src/lib/consensus/beacon-api.ts +++ b/packages/core/src/lib/consensus/beacon-api.ts @@ -292,7 +292,7 @@ async function fetchBeaconProofAttempt( config.slotsPerEpoch, ); - // Compute sync periods — bootstrap was already validated by fetchBootstrapWithFallback + // Compute sync periods (bootstrap was already validated by fetchBootstrapWithFallback) const parsedBootstrap = BootstrapSchema.parse(bootstrap); const bootstrapPeriod = Math.floor( Number(parsedBootstrap.data.header.beacon.slot) / slotsPerPeriod diff --git a/packages/core/src/lib/package/__tests__/creator.test.ts b/packages/core/src/lib/package/__tests__/creator.test.ts index 8e9a8e9a..c1e84d09 100644 --- a/packages/core/src/lib/package/__tests__/creator.test.ts +++ b/packages/core/src/lib/package/__tests__/creator.test.ts @@ -206,7 +206,7 @@ describe("finalizeEvidenceExport", () => { expect(finalized.exportContract?.status).toBe("complete"); }); - it("marks export partial when simulation witness replay inputs are missing", () => { + it("marks full simulation as fully-verifiable even without witness replay inputs", () => { const base = createEvidencePackage(COWSWAP_TWAP_TX, CHAIN_ID, TX_URL); const evidence = { ...base, @@ -272,12 +272,105 @@ describe("finalizeEvidenceExport", () => { simulationFailed: false, }); + expect(finalized.exportContract?.mode).toBe("fully-verifiable"); + expect(finalized.exportContract?.isFullyVerifiable).toBe(true); + expect(finalized.exportContract?.reasons).not.toContain("missing-simulation-witness"); + }); + + it("marks witness-only package as partial when witness replay inputs are missing", () => { + const base = createEvidencePackage(COWSWAP_TWAP_TX, CHAIN_ID, TX_URL); + const evidence = { + ...base, + transaction: { + ...base.transaction, + operation: 0 as const, + }, + onchainPolicyProof: { + blockNumber: 1, + stateRoot: + "0xaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccdd", + accountProof: { + address: COWSWAP_TWAP_TX.safe, + balance: "0", + codeHash: + "0x1111111111111111111111111111111111111111111111111111111111111111", + nonce: 0, + storageHash: + "0x2222222222222222222222222222222222222222222222222222222222222222", + accountProof: [], + storageProof: [], + }, + decodedPolicy: { + owners: [COWSWAP_TWAP_TX.confirmations[0].owner], + threshold: 1, + nonce: 0, + modules: [], + guard: "0x0000000000000000000000000000000000000000", + fallbackHandler: "0x0000000000000000000000000000000000000000", + singleton: "0x0000000000000000000000000000000000000000", + }, + trust: "rpc-sourced" as const, + }, + consensusProof: { + checkpoint: + "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + bootstrap: "{}", + updates: [], + finalityUpdate: "{}", + network: "mainnet" as const, + stateRoot: + "0xaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccdd", + blockNumber: 1, + finalizedSlot: 1, + }, + simulation: { + success: true, + returnData: "0x", + gasUsed: "1", + logs: [], + blockNumber: 1, + trust: "rpc-sourced" as const, + }, + simulationWitness: { + witnessOnly: true, + chainId: CHAIN_ID, + safeAddress: COWSWAP_TWAP_TX.safe, + blockNumber: 1, + stateRoot: + "0xaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccdd", + safeAccountProof: { + address: COWSWAP_TWAP_TX.safe, + balance: "0", + codeHash: + "0x1111111111111111111111111111111111111111111111111111111111111111", + nonce: 0, + storageHash: + "0x2222222222222222222222222222222222222222222222222222222222222222", + accountProof: [], + storageProof: [], + }, + overriddenSlots: [], + simulationDigest: + "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + }, + }; + + const finalized = finalizeEvidenceExport(evidence, { + rpcProvided: true, + consensusProofAttempted: true, + consensusProofFailed: false, + onchainPolicyProofAttempted: true, + onchainPolicyProofFailed: false, + simulationAttempted: true, + simulationFailed: false, + }); + expect(finalized.exportContract?.mode).toBe("partial"); expect(finalized.exportContract?.isFullyVerifiable).toBe(false); expect(finalized.exportContract?.reasons).toContain("missing-simulation-witness"); }); - it("marks export partial when simulation witness replay block context is missing", () => { + it("marks full simulation as fully-verifiable even when replay block context is missing", () => { const base = createEvidencePackage(COWSWAP_TWAP_TX, CHAIN_ID, TX_URL); const evidence = { ...base, @@ -373,12 +466,121 @@ describe("finalizeEvidenceExport", () => { simulationFailed: false, }); - expect(finalized.exportContract?.mode).toBe("partial"); - expect(finalized.exportContract?.isFullyVerifiable).toBe(false); - expect(finalized.exportContract?.reasons).toContain("missing-simulation-witness"); + expect(finalized.exportContract?.mode).toBe("fully-verifiable"); + expect(finalized.exportContract?.isFullyVerifiable).toBe(true); + expect(finalized.exportContract?.reasons).not.toContain("missing-simulation-witness"); + }); + + it("marks full DELEGATECALL simulation as fully-verifiable (replay not needed)", () => { + const base = createEvidencePackage(COWSWAP_TWAP_TX, CHAIN_ID, TX_URL); + const evidence = { + ...base, + transaction: { + ...base.transaction, + operation: 1 as const, + }, + onchainPolicyProof: { + blockNumber: 1, + stateRoot: + "0xaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccdd", + accountProof: { + address: COWSWAP_TWAP_TX.safe, + balance: "0", + codeHash: + "0x1111111111111111111111111111111111111111111111111111111111111111", + nonce: 0, + storageHash: + "0x2222222222222222222222222222222222222222222222222222222222222222", + accountProof: [], + storageProof: [], + }, + decodedPolicy: { + owners: [COWSWAP_TWAP_TX.confirmations[0].owner], + threshold: 1, + nonce: 0, + modules: [], + guard: "0x0000000000000000000000000000000000000000", + fallbackHandler: "0x0000000000000000000000000000000000000000", + singleton: "0x0000000000000000000000000000000000000000", + }, + trust: "rpc-sourced" as const, + }, + consensusProof: { + checkpoint: + "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + bootstrap: "{}", + updates: [], + finalityUpdate: "{}", + network: "mainnet" as const, + stateRoot: + "0xaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccdd", + blockNumber: 1, + finalizedSlot: 1, + }, + simulation: { + success: true, + returnData: "0x", + gasUsed: "1", + logs: [], + blockNumber: 1, + trust: "rpc-sourced" as const, + }, + simulationWitness: { + chainId: CHAIN_ID, + safeAddress: COWSWAP_TWAP_TX.safe, + blockNumber: 1, + stateRoot: + "0xaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccddaabbccdd", + safeAccountProof: { + address: COWSWAP_TWAP_TX.safe, + balance: "0", + codeHash: + "0x1111111111111111111111111111111111111111111111111111111111111111", + nonce: 0, + storageHash: + "0x2222222222222222222222222222222222222222222222222222222222222222", + accountProof: [], + storageProof: [], + }, + overriddenSlots: [], + simulationDigest: + "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + replayBlock: { + timestamp: "1700000000", + gasLimit: "30000000", + baseFeePerGas: "1", + beneficiary: "0x0000000000000000000000000000000000000000", + }, + replayAccounts: [ + { + address: COWSWAP_TWAP_TX.safe, + balance: "0x0", + nonce: 0, + code: "0x", + storage: {}, + }, + ], + }, + }; + + const finalized = finalizeEvidenceExport(evidence, { + rpcProvided: true, + consensusProofAttempted: true, + consensusProofFailed: false, + onchainPolicyProofAttempted: true, + onchainPolicyProofFailed: false, + simulationAttempted: true, + simulationFailed: false, + }); + + expect(finalized.exportContract?.mode).toBe("fully-verifiable"); + expect(finalized.exportContract?.isFullyVerifiable).toBe(true); + expect(finalized.exportContract?.reasons).not.toContain( + "simulation-replay-unsupported-operation" + ); }); - it("marks export partial for DELEGATECALL even with replay witness inputs", () => { + it("marks witness-only DELEGATECALL package as partial", () => { const base = createEvidencePackage(COWSWAP_TWAP_TX, CHAIN_ID, TX_URL); const evidence = { ...base, @@ -433,6 +635,7 @@ describe("finalizeEvidenceExport", () => { trust: "rpc-sourced" as const, }, simulationWitness: { + witnessOnly: true, chainId: CHAIN_ID, safeAddress: COWSWAP_TWAP_TX.safe, blockNumber: 1, @@ -558,7 +761,7 @@ describe("finalizeEvidenceExport", () => { network: "linea" as const, }, ])( - "marks export partial when $consensusMode consensus artifact exists — only beacon is verifier-supported", + "marks export partial when $consensusMode consensus artifact exists (only beacon is verifier-supported)", ({ chainId, consensusMode, network }) => { const base = createEvidencePackage(COWSWAP_TWAP_TX, chainId, TX_URL); const evidence = { diff --git a/packages/core/src/lib/package/creator.ts b/packages/core/src/lib/package/creator.ts index a93d9517..7a5dce2d 100644 --- a/packages/core/src/lib/package/creator.ts +++ b/packages/core/src/lib/package/creator.ts @@ -308,6 +308,11 @@ export function finalizeEvidenceExport( const hasReplaySupportedOperation = evidence.transaction.operation === 0; const hasReplayCapableSimulationWitnessInputs = hasReplaySupportedOperation && hasSimulationWitnessReplayInputs; + // For witness-only packages the desktop verifier must replay the simulation + // locally, so replay-capable inputs are required. For full simulations the + // results are embedded in the package and verified structurally. Replay + // inputs are informational only and must not gate the fully-verifiable flag. + const witnessOnly = evidence.simulationWitness?.witnessOnly === true; const reasons = new Set(); if (!hasConsensusProofArtifact) { @@ -350,17 +355,20 @@ export function finalizeEvidenceExport( } else { reasons.add("missing-simulation"); } - } else if (!hasReplaySupportedOperation) { + } else if (witnessOnly && !hasReplaySupportedOperation) { reasons.add("simulation-replay-unsupported-operation"); - } else if (!hasSimulationWitnessReplayInputs) { + } else if (witnessOnly && !hasSimulationWitnessReplayInputs) { reasons.add("missing-simulation-witness"); } + const simulationReplayOk = hasSimulation && + (witnessOnly ? hasReplayCapableSimulationWitnessInputs : true); + const isFullyVerifiable = hasVerifierSupportedConsensusProof && hasOnchainPolicyProof && hasSimulation && - hasReplayCapableSimulationWitnessInputs; + simulationReplayOk; const diagnostics: EvidenceExportContract["diagnostics"] = options.witnessGenerationError !== undefined ? { witnessGenerationError: options.witnessGenerationError || "(unknown error)" } diff --git a/packages/core/src/lib/safe/api.ts b/packages/core/src/lib/safe/api.ts index e7c69e32..b8f7be32 100644 --- a/packages/core/src/lib/safe/api.ts +++ b/packages/core/src/lib/safe/api.ts @@ -2,7 +2,7 @@ import { z } from "zod"; import { SafeTransaction, SafeTransactionList, safeTransactionSchema, safeTransactionListSchema } from "../types"; import { getSafeApiUrl } from "./url-parser"; -// Minimal schema for the Safe info endpoint — only the fields we need. +// Minimal schema for the Safe info endpoint -- only the fields we need. // Validates nonce at the trust boundary to prevent a malicious API from // injecting arbitrary values that would affect pending-transaction filtering. const safeInfoNonceSchema = z.object({ diff --git a/packages/core/src/lib/safe/signatures.ts b/packages/core/src/lib/safe/signatures.ts index 8e40db2e..210384b9 100644 --- a/packages/core/src/lib/safe/signatures.ts +++ b/packages/core/src/lib/safe/signatures.ts @@ -58,7 +58,7 @@ export async function verifySignature( return { status: valid ? "valid" : "invalid", recoveredSigner }; } catch (err) { // ECDSA recovery can fail for malformed signatures (invalid curve points, - // out-of-range s values, etc). This is not an internal error — it means the + // out-of-range s values, etc). This is not an internal error -- it means the // signature data is cryptographically invalid. We surface the underlying // reason so auditors/users can distinguish "can't verify this type" from // "verification threw an error". diff --git a/packages/core/src/lib/settings/store.ts b/packages/core/src/lib/settings/store.ts index 9f63c251..9edf2cdf 100644 --- a/packages/core/src/lib/settings/store.ts +++ b/packages/core/src/lib/settings/store.ts @@ -82,7 +82,7 @@ export async function resetSettingsConfig( } export async function exportSettingsConfig(store: SettingsStore): Promise { - // Warning is intentionally discarded here — load warnings are surfaced + // Warning is intentionally discarded here -- load warnings are surfaced // through the normal bootstrap path (UI banner / CLI stderr), and the // export function only needs the resolved config. const { config } = await loadSettingsConfig(store); diff --git a/packages/core/src/lib/simulation/__tests__/summary.test.ts b/packages/core/src/lib/simulation/__tests__/summary.test.ts index 6cd5999c..6143aad6 100644 --- a/packages/core/src/lib/simulation/__tests__/summary.test.ts +++ b/packages/core/src/lib/simulation/__tests__/summary.test.ts @@ -554,7 +554,7 @@ describe("computeProvenBalanceChanges", () => { amountRaw: (100n * 10n ** 18n).toString(), direction: "send", }]; - // State diff on a different address — no match + // State diff on a different address -- no match const diffs: StateDiffEntry[] = [{ address: DAI, key: "0x" + "ff".repeat(32), @@ -620,7 +620,7 @@ describe("computeProvenBalanceChanges", () => { amountRaw: (50n * 10n ** 18n).toString(), direction: "send", }, - // Duplicate transfer for the same sender — should not create a second entry + // Duplicate transfer for the same sender -- should not create a second entry { kind: "transfer", token: DAI, diff --git a/packages/core/src/lib/simulation/fetcher.ts b/packages/core/src/lib/simulation/fetcher.ts index 02205808..127a8200 100644 --- a/packages/core/src/lib/simulation/fetcher.ts +++ b/packages/core/src/lib/simulation/fetcher.ts @@ -28,6 +28,7 @@ import { computeSafeTxHash } from "../safe/hash"; import { CHAIN_BY_ID, DEFAULT_RPC_URLS, getExecutionCapability } from "../chains"; import { SENTINEL, + SLOT_SINGLETON, SLOT_OWNER_COUNT, SLOT_THRESHOLD, SLOT_NONCE, @@ -291,7 +292,7 @@ export async function fetchSimulation( } catch { // Expected: estimateGas may fail if the node doesn't support stateOverride // on eth_estimateGas, or if the call reverts (we already checked success). - // Masked: transient RPC errors (rate-limit, timeout) — acceptable because + // Masked: transient RPC errors (rate-limit, timeout) -- acceptable because // gasUsed is informational only and the simulation already succeeded. } } @@ -435,6 +436,20 @@ export async function fetchSimulationWitness( ); const resolvedReplayAccounts = replayAccounts ?? fallbackReplayAccounts; + // The prestateTracer with diffMode:true only captures MODIFIED state. + // Slots that are only READ during execution (slot 0 / singleton pointer, + // override slots like ownerCount/threshold/owners that don't change) are + // missing. The fallback path has the same gap. Augment both. + if (resolvedReplayAccounts) { + await augmentReplayAccountsForSafe( + client, + safeAddress, + resolvedReplayAccounts, + stateDiff, + blockNumber + ); + } + return { chainId, safeAddress, @@ -479,6 +494,83 @@ function normalizeHex(value: string): string { return value.startsWith("0x") ? value : `0x${value}`; } +/** + * Ensure replay accounts contain everything the local EVM needs to execute + * the Safe's `execTransaction` call. Both the prestateTracer (diffMode:true + * only captures modified state) and the simple-transfer fallback can produce + * accounts missing: + * + * 1. Slot 0 (singleton pointer) -- read-only, never modified. + * 2. Override slots that are only READ during execution (ownerCount, + * threshold, owners, guard, fallback handler, modules). + * 3. The singleton contract itself (accessed via DELEGATECALL, code never + * modified so absent from diffMode traces). + */ +async function augmentReplayAccountsForSafe( + client: ReturnType, + safeAddress: Address, + accounts: NonNullable, + stateDiff: Array<{ slot: Hex; value: Hex }>, + blockNumber: bigint +): Promise { + const safeAccount = accounts.find( + (a) => a.address.toLowerCase() === safeAddress.toLowerCase() + ); + if (!safeAccount) return; + + // 1. Ensure all override slots are present. The prestateTracer with + // diffMode only returns slots that were MODIFIED during execution. + // Override slots that are only READ (ownerCount, threshold, owners, + // guard, fallback handler, modules) would be missing. + for (const entry of stateDiff) { + if (!(entry.slot in safeAccount.storage)) { + safeAccount.storage[entry.slot] = entry.value; + } + } + + // 2. Ensure slot 0 (singleton/masterCopy) is present. The Safe proxy's + // bytecode reads SLOAD(0) to find the implementation address for + // DELEGATECALL. Without this, the replay delegates to address(0). + const singletonSlotKey = slotToKey(SLOT_SINGLETON); + if (!(singletonSlotKey in safeAccount.storage)) { + const value = await client.getStorageAt({ + address: safeAddress, + slot: singletonSlotKey, + blockNumber, + }); + if (value) { + safeAccount.storage[singletonSlotKey] = value; + } + } + + // 3. Ensure the singleton contract is present so the DELEGATECALL has + // code to execute. Its own storage is unused (DELEGATECALL runs in + // the proxy's storage context). + const singletonSlotValue = safeAccount.storage[singletonSlotKey]; + if (!singletonSlotValue) return; + + const singletonAddr = ("0x" + singletonSlotValue.slice(26)).toLowerCase() as Address; + if (singletonAddr === "0x0000000000000000000000000000000000000000") return; + + const hasSingleton = accounts.some( + (a) => a.address.toLowerCase() === singletonAddr + ); + if (hasSingleton) return; + + const [balance, nonce, code] = await Promise.all([ + client.getBalance({ address: singletonAddr as Address, blockNumber }), + client.getTransactionCount({ address: singletonAddr as Address, blockNumber }), + client.getCode({ address: singletonAddr as Address, blockNumber }), + ]); + accounts.push({ + address: singletonAddr, + balance: normalizeHex(toHex(balance)), + nonce, + code: code && code !== "0x" ? normalizeHex(code) : "0x", + storage: {}, + }); +} + /** * Walk viem's error cause chain to extract revert data. * Viem wraps reverts as CallExecutionError → RpcRequestError. @@ -635,7 +727,7 @@ async function debugTraceCallWithOverrides( } catch { // Expected: Gnosis-style RPCs reject `stateOverrides` (plural) and require // `stateOverride` (singular). The first request fails with a JSON-RPC error. - // Masked: transient network errors on the first attempt — acceptable because + // Masked: transient network errors on the first attempt -- acceptable because // the singular retry will also fail, and the outer catch handles it. return await client.request({ method: "debug_traceCall" as "eth_call", @@ -744,7 +836,7 @@ async function tryTraceCall( gasUsed = BigInt(frame.gasUsed).toString(); } catch { // Expected: malformed gasUsed hex from non-standard RPC responses. - // Masked: nothing critical — gasUsed is informational; the trace + // Masked: nothing critical -- gasUsed is informational; the trace // data (logs, native transfers) was already collected above. gasUsed = null; } @@ -757,7 +849,7 @@ async function tryTraceCall( // prestateTracer and falls back to estimateGas. // Masked: transient RPC errors (rate-limit, timeout) are treated as // "feature unavailable" for this simulation. This is acceptable because - // simulation still succeeds via eth_call — traces are an enhancement. + // simulation still succeeds via eth_call -- traces are an enhancement. return { logs: [], nativeTransfers: [], gasUsed: null, available: false }; } } @@ -805,7 +897,7 @@ async function tryRunPrestateTrace( } catch { // Expected: prestateTracer is not supported by all RPCs (same as callTracer). // Returns undefined so the caller skips state diff extraction. - // Masked: transient RPC errors — acceptable because state diffs are an + // Masked: transient RPC errors -- acceptable because state diffs are an // enhancement over event-based heuristics, not a required feature. return undefined; } @@ -891,7 +983,7 @@ async function tryCollectReplayAccounts( // Expected: prestateTracer unavailable or trace response missing required // accounts. Returns undefined so the caller falls back to // tryCollectSimpleTransferReplayAccounts (manual EOA snapshot). - // Masked: transient RPC errors — acceptable because replay accounts are + // Masked: transient RPC errors -- acceptable because replay accounts are // a witness enhancement; the simulation itself already completed. return undefined; } @@ -919,13 +1011,38 @@ async function tryCollectSimpleTransferReplayAccounts( return undefined; } - const safeOverrideStorage = Object.fromEntries( + // Read slot 0 (singleton/masterCopy) from the Safe. The proxy's bytecode + // does SLOAD(0) to find the implementation address, then DELEGATECALLs to it. + // Without this, the local replay delegatecalls to address(0) and gets 0x. + const singletonSlotKey = slotToKey(SLOT_SINGLETON); + const singletonSlotValue = await client.getStorageAt({ + address: safeAddress, + slot: singletonSlotKey, + blockNumber, + }); + const singletonAddress = ( + singletonSlotValue + ? ("0x" + singletonSlotValue.slice(26)) as Address // last 20 bytes + : undefined + ); + + const safeOverrideStorage: Record = Object.fromEntries( buildSafeStateDiff(transaction.nonce, SIMULATION_ACCOUNT.address).map((entry) => [ entry.slot, entry.value, ]) ); + // Include the real on-chain singleton pointer so the proxy can delegatecall. + if (singletonSlotValue) { + safeOverrideStorage[singletonSlotKey] = singletonSlotValue; + } + const addresses: Address[] = [safeAddress, recipient, SIMULATION_ACCOUNT.address]; + // Include the singleton contract so the delegatecall has code to execute. + if (singletonAddress && singletonAddress !== "0x0000000000000000000000000000000000000000") { + addresses.push(singletonAddress); + } + const snapshots = await Promise.all( addresses.map(async (address) => { const [balance, nonce, code] = await Promise.all([ @@ -951,7 +1068,7 @@ async function tryCollectSimpleTransferReplayAccounts( } catch { // Expected: RPC calls for balance/nonce/code may fail on nodes that don't // support historical state queries at the pinned blockNumber. - // Masked: transient errors — acceptable because this is the last-resort + // Masked: transient errors -- acceptable because this is the last-resort // fallback for simple native transfers only; the witness will be generated // without replayAccounts, limiting offline replay but not blocking generation. return undefined; diff --git a/packages/core/src/lib/simulation/slot-decoder.ts b/packages/core/src/lib/simulation/slot-decoder.ts index 71686921..88accdf8 100644 --- a/packages/core/src/lib/simulation/slot-decoder.ts +++ b/packages/core/src/lib/simulation/slot-decoder.ts @@ -8,7 +8,7 @@ * slot keys across known ERC-20 layouts and check if any match the * observed state diffs. When a match is found, the before/after values * from the state diff provide **proven** post-state balances/allowances - * — not just event heuristics. + * rather than just event heuristics. * * This is the foundation for issue #105: replacing event-only approval * heuristics with proven post-state values. @@ -49,7 +49,7 @@ const ERC20_LAYOUTS: ERC20StorageLayout[] = [ { name: "vyper", balanceSlot: 1n, allowanceSlot: 2n }, // DAI and MakerDAO tokens { name: "dai", balanceSlot: 2n, allowanceSlot: 3n }, - // WETH (balance at slot 3, no standard allowance — but try 4) + // WETH (balance at slot 3, no standard allowance -- but try 4) { name: "weth", balanceSlot: 3n, allowanceSlot: 4n }, // USDC / bridged tokens behind proxies (slot 9/10) { name: "usdc-proxy", balanceSlot: 9n, allowanceSlot: 10n }, diff --git a/packages/core/src/lib/simulation/summary.ts b/packages/core/src/lib/simulation/summary.ts index 2fabde8f..7a11b50d 100644 --- a/packages/core/src/lib/simulation/summary.ts +++ b/packages/core/src/lib/simulation/summary.ts @@ -108,7 +108,7 @@ export type RemainingApproval = { * When `stateDiffs` are provided, the function attempts to correlate * Approval events with proven storage-level data. For (token, spender) * pairs where a state diff match is found, the proven post-state value - * replaces the event-based heuristic — correctly handling cases where + * replaces the event-based heuristic, correctly handling cases where * allowances are consumed via `transferFrom` without a new `Approval` event. */ export function computeRemainingApprovals( @@ -126,7 +126,7 @@ function buildRemainingApprovals( ): RemainingApproval[] { const provenByPair = new Map(); for (const proven of decoded.allowances) { - // Keep only the first match per (token, owner, spender) — layouts are + // Keep only the first match per (token, owner, spender) -- layouts are // tried in priority order so the first match is the best one const key = `${proven.token}:${proven.owner}:${proven.spender}`; if (!provenByPair.has(key)) { @@ -270,7 +270,7 @@ export type StateDiffSummary = { * Summarize storage-level state diffs, correlating with decoded events. * * Contracts that modified storage without emitting any decoded events are - * flagged as "silent" — a signal that the transaction has effects not + * flagged as "silent", a signal that the transaction has effects not * visible from event logs alone (e.g. allowance changes via transferFrom, * or direct storage writes via delegatecall). * diff --git a/packages/core/src/lib/types.ts b/packages/core/src/lib/types.ts index 7612c777..58ca2eb2 100644 --- a/packages/core/src/lib/types.ts +++ b/packages/core/src/lib/types.ts @@ -193,7 +193,7 @@ const beaconConsensusProofSchema = consensusProofBaseSchema.extend({ finalityUpdate: z.string(), /** Beacon network identifier for selecting the correct fork config and genesis root. */ network: z.enum(CONSENSUS_NETWORKS), - /** Beacon slot of the finalized header in the finality update. Informational metadata only — not consumed by the desktop verifier. */ + /** Beacon slot of the finalized header in the finality update. Informational metadata only, not consumed by the desktop verifier. */ finalizedSlot: z.number().int().optional(), }); From 3444e563ce3c6d129202a007b0ca73a8916a66cc Mon Sep 17 00:00:00 2001 From: Thomas Marchand Date: Thu, 26 Feb 2026 07:16:33 +0000 Subject: [PATCH 2/9] feat(core): add replayCalldata to witness for execTransaction-level replay The local replay now calls execTransaction on the Safe proxy instead of the inner transaction directly when replayCalldata is present. This ensures the replay return data matches the simulation's ABI-encoded execTransaction response (e.g. abi.encode(true)). --- .../src-tauri/src/simulation_replay.rs | 111 ++++++++++++------ packages/core/scripts/test-replay-witness.ts | 1 + packages/core/src/lib/simulation/fetcher.ts | 1 + packages/core/src/lib/types.ts | 4 + 4 files changed, 81 insertions(+), 36 deletions(-) diff --git a/apps/desktop/src-tauri/src/simulation_replay.rs b/apps/desktop/src-tauri/src/simulation_replay.rs index 2ce391ca..772d33ad 100644 --- a/apps/desktop/src-tauri/src/simulation_replay.rs +++ b/apps/desktop/src-tauri/src/simulation_replay.rs @@ -75,6 +75,7 @@ pub struct ReplayWitness { pub replay_accounts: Option>, pub replay_caller: Option, pub replay_gas_limit: Option, + pub replay_calldata: Option, pub witness_only: Option, } @@ -356,48 +357,70 @@ fn execute_replay( }); let caller_nonce = caller_account.map(|account| account.nonce).unwrap_or(0); - let to = parse_address(&input.transaction.to, "transaction.to")?; - let inner_value = parse_u256(&input.transaction.value) - .map_err(|err| format!("invalid transaction.value: {err}"))?; - - let data = match input.transaction.data.as_deref() { - Some(raw) => parse_bytes(raw).map_err(|err| format!("invalid transaction.data: {err}"))?, - None => Bytes::new(), - }; - - let gas_limit = match input.simulation_witness.replay_gas_limit { - Some(limit) => limit, - None => match input.transaction.safe_tx_gas.as_deref() { + // When replayCalldata is present, call execTransaction on the Safe proxy + // instead of the inner transaction directly. This ensures the replay return + // data matches the simulation's execTransaction return (e.g. abi.encode(true)). + let has_replay_calldata = input.simulation_witness.replay_calldata.is_some(); + + let (tx_target, tx_value, tx_data, gas_limit) = if let Some(ref raw_calldata) = + input.simulation_witness.replay_calldata + { + let safe_addr = parse_address(&input.safe_address, "safeAddress")?; + let calldata = parse_bytes(raw_calldata) + .map_err(|err| format!("invalid simulationWitness.replayCalldata: {err}"))?; + let limit = input.simulation_witness.replay_gas_limit.unwrap_or(10_000_000); + (safe_addr, U256::ZERO, calldata, limit) + } else { + let to = parse_address(&input.transaction.to, "transaction.to")?; + let inner_value = parse_u256(&input.transaction.value) + .map_err(|err| format!("invalid transaction.value: {err}"))?; + let data = match input.transaction.data.as_deref() { Some(raw) => { - let parsed = parse_u256(raw) - .map_err(|err| format!("invalid transaction.safeTxGas: {err}"))?; - let capped = parsed.min(U256::from(u64::MAX)); - let as_u64 = capped.to::(); - if as_u64 == 0 { - 3_000_000 - } else { - as_u64 - } + parse_bytes(raw).map_err(|err| format!("invalid transaction.data: {err}"))? } - None => 3_000_000, - }, + None => Bytes::new(), + }; + let limit = match input.simulation_witness.replay_gas_limit { + Some(limit) => limit, + None => match input.transaction.safe_tx_gas.as_deref() { + Some(raw) => { + let parsed = parse_u256(raw) + .map_err(|err| format!("invalid transaction.safeTxGas: {err}"))?; + let capped = parsed.min(U256::from(u64::MAX)); + let as_u64 = capped.to::(); + if as_u64 == 0 { + 3_000_000 + } else { + as_u64 + } + } + None => 3_000_000, + }, + }; + (to, inner_value, data, limit) }; - let tx_kind = match input.transaction.operation { - 0 => TxKind::Call(to), - 1 => return Err( - "transaction.operation=1 (DELEGATECALL) is not replay-supported in the local verifier." - .to_string(), - ), - value => { - return Err(format!( - "invalid transaction.operation: expected 0 (CALL) or 1 (DELEGATECALL), got {value}" - )) + let tx_kind = if has_replay_calldata { + TxKind::Call(tx_target) + } else { + match input.transaction.operation { + 0 => TxKind::Call(tx_target), + 1 => { + return Err( + "transaction.operation=1 (DELEGATECALL) is not replay-supported in the local verifier." + .to_string(), + ) + } + value => { + return Err(format!( + "invalid transaction.operation: expected 0 (CALL) or 1 (DELEGATECALL), got {value}" + )) + } } }; let gas_price = resolve_replay_gas_price(input)?; - let required_caller_balance = (U256::from(gas_limit) * U256::from(gas_price)) + inner_value; + let required_caller_balance = (U256::from(gas_limit) * U256::from(gas_price)) + tx_value; for account in accounts { let address = parse_address(&account.address, "replay account address")?; @@ -443,8 +466,8 @@ fn execute_replay( .gas_price(gas_price) .nonce(caller_nonce) .chain_id(Some(input.chain_id)) - .value(inner_value) - .data(data) + .value(tx_value) + .data(tx_data) .build() .map_err(|err| format!("failed to build replay tx: {err:?}"))?; @@ -811,6 +834,7 @@ mod tests { replay_accounts: None, replay_caller: None, replay_gas_limit: None, + replay_calldata: None, witness_only: None, }, }); @@ -848,6 +872,7 @@ mod tests { replay_accounts: Some(vec![caller_account(caller), target_account(target, code)]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: None, }, }); @@ -889,6 +914,7 @@ mod tests { replay_accounts: Some(vec![caller_account(caller), target_account(target, code)]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: None, }, }); @@ -927,6 +953,7 @@ mod tests { replay_accounts: Some(vec![caller_account(caller), target_account(target, code)]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: None, }, }); @@ -968,6 +995,7 @@ mod tests { ]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: None, }, }); @@ -1013,6 +1041,7 @@ mod tests { ]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(3_000_000), + replay_calldata: None, witness_only: Some(true), }, }); @@ -1059,6 +1088,7 @@ mod tests { replay_accounts: Some(vec![caller_account(caller), target_account(target, code)]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: Some(true), }, }); @@ -1106,6 +1136,7 @@ mod tests { ]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: Some(true), }, }); @@ -1158,6 +1189,7 @@ mod tests { ]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(800000), + replay_calldata: None, witness_only: Some(true), }, }); @@ -1207,6 +1239,7 @@ mod tests { ]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(800000), + replay_calldata: None, witness_only: Some(true), }, }); @@ -1249,6 +1282,7 @@ mod tests { replay_accounts: Some(vec![caller_account(caller), target_account(target, "0x")]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: None, }, }); @@ -1338,6 +1372,7 @@ mod tests { ]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: None, }, }; @@ -1387,6 +1422,7 @@ mod tests { replay_accounts: Some(vec![caller_account(caller), target_account(target, "0x")]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: Some(true), }, }); @@ -1431,6 +1467,7 @@ mod tests { replay_accounts: Some(vec![caller_account(caller), target_account(target, code)]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: Some(true), }, }); @@ -1479,6 +1516,7 @@ mod tests { ]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: Some(true), }, }); @@ -1529,6 +1567,7 @@ mod tests { ]), replay_caller: Some(caller.to_string()), replay_gas_limit: Some(500000), + replay_calldata: None, witness_only: Some(true), }, }); diff --git a/packages/core/scripts/test-replay-witness.ts b/packages/core/scripts/test-replay-witness.ts index dea61f5a..191a0c9a 100644 --- a/packages/core/scripts/test-replay-witness.ts +++ b/packages/core/scripts/test-replay-witness.ts @@ -106,6 +106,7 @@ async function main() { replayAccounts: witness.replayAccounts, replayCaller: witness.replayCaller, replayGasLimit: witness.replayGasLimit, + replayCalldata: witness.replayCalldata, witnessOnly: true, }, }; diff --git a/packages/core/src/lib/simulation/fetcher.ts b/packages/core/src/lib/simulation/fetcher.ts index 127a8200..9a824579 100644 --- a/packages/core/src/lib/simulation/fetcher.ts +++ b/packages/core/src/lib/simulation/fetcher.ts @@ -484,6 +484,7 @@ export async function fetchSimulationWitness( replayAccounts: resolvedReplayAccounts, replayCaller: SIMULATION_ACCOUNT.address, replayGasLimit: normalizeReplayGasLimit(transaction.safeTxGas), + replayCalldata: calldata, }; } diff --git a/packages/core/src/lib/types.ts b/packages/core/src/lib/types.ts index 58ca2eb2..55208ff7 100644 --- a/packages/core/src/lib/types.ts +++ b/packages/core/src/lib/types.ts @@ -281,6 +281,10 @@ export const simulationWitnessSchema = z.object({ ).optional(), replayCaller: addressSchema.optional(), replayGasLimit: z.number().int().positive().optional(), + /** ABI-encoded execTransaction calldata. When present, the local replay + * calls the Safe proxy with this calldata instead of the inner transaction + * directly, so the return data matches the simulation's execTransaction. */ + replayCalldata: hexDataSchema.optional(), /** When true, packaged simulation effects (logs/nativeTransfers) are retained * but must be re-derived from local replay during verification. Set by the * creator when witness contains complete replay inputs (world-state accounts From fbef8aa6f4f4978e78eabebbbd4265ef9886f6b5 Mon Sep 17 00:00:00 2001 From: "Thomas Marchand (agent)" Date: Thu, 26 Feb 2026 07:20:34 +0000 Subject: [PATCH 3/9] fix(ci): format simulation replay test --- apps/desktop/src-tauri/src/simulation_replay.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/desktop/src-tauri/src/simulation_replay.rs b/apps/desktop/src-tauri/src/simulation_replay.rs index 772d33ad..e69fdacd 100644 --- a/apps/desktop/src-tauri/src/simulation_replay.rs +++ b/apps/desktop/src-tauri/src/simulation_replay.rs @@ -1527,12 +1527,8 @@ mod tests { // With slot 0 + singleton → correct delegatecall → match let mut proxy_storage = BTreeMap::new(); proxy_storage.insert( - "0x0000000000000000000000000000000000000000000000000000000000000000" - .to_string(), - format!( - "0x000000000000000000000000{}", - &singleton_addr[2..] - ), + "0x0000000000000000000000000000000000000000000000000000000000000000".to_string(), + format!("0x000000000000000000000000{}", &singleton_addr[2..]), ); let result_with = verify_simulation_replay(SimulationReplayInput { From 2ef533519989fa99bd327f48b86fdbdbdf0b171c Mon Sep 17 00:00:00 2001 From: "Thomas Marchand (agent)" Date: Thu, 26 Feb 2026 07:22:55 +0000 Subject: [PATCH 4/9] fix(ci): format replay calldata branch --- .../src-tauri/src/simulation_replay.rs | 70 ++++++++++--------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/apps/desktop/src-tauri/src/simulation_replay.rs b/apps/desktop/src-tauri/src/simulation_replay.rs index e69fdacd..c1f04369 100644 --- a/apps/desktop/src-tauri/src/simulation_replay.rs +++ b/apps/desktop/src-tauri/src/simulation_replay.rs @@ -362,43 +362,45 @@ fn execute_replay( // data matches the simulation's execTransaction return (e.g. abi.encode(true)). let has_replay_calldata = input.simulation_witness.replay_calldata.is_some(); - let (tx_target, tx_value, tx_data, gas_limit) = if let Some(ref raw_calldata) = - input.simulation_witness.replay_calldata - { - let safe_addr = parse_address(&input.safe_address, "safeAddress")?; - let calldata = parse_bytes(raw_calldata) - .map_err(|err| format!("invalid simulationWitness.replayCalldata: {err}"))?; - let limit = input.simulation_witness.replay_gas_limit.unwrap_or(10_000_000); - (safe_addr, U256::ZERO, calldata, limit) - } else { - let to = parse_address(&input.transaction.to, "transaction.to")?; - let inner_value = parse_u256(&input.transaction.value) - .map_err(|err| format!("invalid transaction.value: {err}"))?; - let data = match input.transaction.data.as_deref() { - Some(raw) => { - parse_bytes(raw).map_err(|err| format!("invalid transaction.data: {err}"))? - } - None => Bytes::new(), - }; - let limit = match input.simulation_witness.replay_gas_limit { - Some(limit) => limit, - None => match input.transaction.safe_tx_gas.as_deref() { + let (tx_target, tx_value, tx_data, gas_limit) = + if let Some(ref raw_calldata) = input.simulation_witness.replay_calldata { + let safe_addr = parse_address(&input.safe_address, "safeAddress")?; + let calldata = parse_bytes(raw_calldata) + .map_err(|err| format!("invalid simulationWitness.replayCalldata: {err}"))?; + let limit = input + .simulation_witness + .replay_gas_limit + .unwrap_or(10_000_000); + (safe_addr, U256::ZERO, calldata, limit) + } else { + let to = parse_address(&input.transaction.to, "transaction.to")?; + let inner_value = parse_u256(&input.transaction.value) + .map_err(|err| format!("invalid transaction.value: {err}"))?; + let data = match input.transaction.data.as_deref() { Some(raw) => { - let parsed = parse_u256(raw) - .map_err(|err| format!("invalid transaction.safeTxGas: {err}"))?; - let capped = parsed.min(U256::from(u64::MAX)); - let as_u64 = capped.to::(); - if as_u64 == 0 { - 3_000_000 - } else { - as_u64 - } + parse_bytes(raw).map_err(|err| format!("invalid transaction.data: {err}"))? } - None => 3_000_000, - }, + None => Bytes::new(), + }; + let limit = match input.simulation_witness.replay_gas_limit { + Some(limit) => limit, + None => match input.transaction.safe_tx_gas.as_deref() { + Some(raw) => { + let parsed = parse_u256(raw) + .map_err(|err| format!("invalid transaction.safeTxGas: {err}"))?; + let capped = parsed.min(U256::from(u64::MAX)); + let as_u64 = capped.to::(); + if as_u64 == 0 { + 3_000_000 + } else { + as_u64 + } + } + None => 3_000_000, + }, + }; + (to, inner_value, data, limit) }; - (to, inner_value, data, limit) - }; let tx_kind = if has_replay_calldata { TxKind::Call(tx_target) From 5ca663467e9c777aad2f1839017c67ee0af3043f Mon Sep 17 00:00:00 2001 From: "Thomas Marchand (agent)" Date: Thu, 26 Feb 2026 07:27:18 +0000 Subject: [PATCH 5/9] docs: tighten auditor guidance and remove stale issue tracking --- AUDIT.md | 74 +++++-------------- .../verification-source-contract.md | 5 +- 2 files changed, 21 insertions(+), 58 deletions(-) diff --git a/AUDIT.md b/AUDIT.md index facde662..097fe212 100644 --- a/AUDIT.md +++ b/AUDIT.md @@ -120,7 +120,7 @@ OP Stack and Linea consensus proofs are RPC-sourced execution header reads — * |---|---|---| | Evidence package JSON | Zod schema | Type confusion, malformed data | | safeTxHash (claimed) | Recomputed, never trusted | **Hash substitution attack** | -| Signatures | Length check + ECDSA recovery | Invalid/malleabile signatures | +| Signatures | Length check + ECDSA recovery | Invalid/malleable signatures | | Consensus proof | BLS verification (Rust) | Forged committee signatures | | Settings file | Zod schema | Malformed user config | @@ -166,52 +166,6 @@ Settings import/export is a local trust boundary (user-supplied JSON parsed by ` | System clock trust for `packagedAt` | Operator responsibility; no independent time source available | | OP Stack/Linea envelope forgery by compromised RPC | Explicitly labeled as partial trust; cannot reach fully-verifiable | | Contract signatures (v=0) not verified offline | Require on-chain call; flagged as warning in verification report | -| Beacon API responses not Zod-validated (generation only) | **Fixed** (PR #173): `FinalityUpdateSchema`, `HeaderResponseSchema`, and `BootstrapSchema` now validate all beacon API consumption sites. `fetchBeaconJson` returns `Promise` instead of `Promise`. | - -### Open Issues - -Canonical source: GitHub issues for this repo -`https://github.com/Th0rgal/SafeLens/issues` - -Snapshot as of **2026-02-24** (synchronized with GitHub issue tracker): - -| Issue | Severity | Scope | -|---|---|---| -| #105 Infer proven post-state balance/allowance deltas (replace event-only approval heuristic) | Medium | simulation interpretation correctness | - -### Closed Issues (previously listed) - -| Issue | Resolution | -|---|---| -| #135 `consensusProof.finalizedSlot` is schema-required but ignored by desktop verifier | Fixed: `finalizedSlot` is now optional (`z.number().int().optional()`) with doc comment clarifying it is informational metadata not consumed by the desktop verifier | -| #134 Generator emits verbose evidence debug logs in production without opt-in | Fixed in PR #143: debug logs gated behind `NEXT_PUBLIC_ENABLE_DEBUG_LOGS` / `NODE_ENV === "development"` | -| #133 Docs mismatch: `AUDIT.md` witness-only simulation effects flow is stale | Fixed in PR #146: AUDIT.md data flow description synchronized with runtime behavior | -| #132 Docs mismatch: `TRUST_ASSUMPTIONS` witness-only simulation effects contract is stale | Fixed in PR #146: witness-only semantics clarified with cross-reference to verification-source-contract | -| #131 Docs mismatch: `TRUST_ASSUMPTIONS` pins evidence package to v1.1 | Fixed in PR #146: version pinning updated to `v1.0/v1.1/v1.2` | -| #127 RPC URL sanitizer misses case-variant credential params | Fixed: `redactRpcUrl` in `rpc-redaction.ts` handles URL-pattern redaction; witness errors also redact URLs via regex | -| #125 Stale consensus-mode schema comment misstates desktop verifier support | Fixed in PR #146: comment updated to document beacon/opstack/linea support | -| #123 Stale `simulationWitness.witnessOnly` schema comment contradicts runtime behavior | Fixed in PR #146: comment updated with when/why context | -| #120 Docs mismatch: README/TRUST_ASSUMPTIONS claim `connect-src 'none'` | Fixed in PR #146: CSP documentation corrected to match Tauri IPC-only policy | -| #119 Architecture doc mismatch: witness-only simulation effects no longer omitted | Fixed in PR #146: architecture contract synchronized with package creator behavior | -| #118 Witness-only verification gap: VerifyScreen can display unverified packaged simulation effects | Fixed in PR #147: effects gated on `replayPassed` and badge gated on `simulationPassed` | -| #117 Witness generation errors are silently swallowed in `enrichWithSimulation` | Fixed in PR #143: `enrichWithSimulation` returns `{ evidence, witnessGenerationError? }` with URL redaction | -| #113 `AUDIT.md` claims `connect-src 'none'` but production CSP allows Tauri IPC origins | Fixed in PR #146: CSP claim corrected | -| #106 Settings loader silently falls back to defaults on read/parse/schema errors | Fixed in PR #144: `loadSettingsConfig` returns `SettingsLoadResult { config, warning? }` with typed warnings surfaced in desktop UI and CLI stderr | -| #137 `simulationWitness.blockNumber` accepts non-integers | Fixed: schema now enforces `z.number().int()` | -| #136 `simulationWitness.chainId` accepts non-integers | Fixed: schema now enforces `z.number().int()` | -| #130 `simulation.blockNumber` accepts non-integers but desktop replay expects `u64` | Fixed: schema now enforces `z.number().int()` | -| #129 `onchain decodedPolicy.nonce` accepts non-integers | Fixed: schema now enforces `z.number().int()` | -| #126 `onchainPolicyProof.blockNumber` accepts non-integers | Fixed: schema now enforces `z.number().int()` | -| #121 `transaction.nonce` accepts non-integers and verifier throws `RangeError` | Fixed: schema now enforces `z.number().int()` | -| #116 `onchain decodedPolicy.threshold` accepts non-integers | Fixed: schema now enforces `z.number().int()` | -| #115 `consensusProof.blockNumber` accepts non-integers but desktop verifier requires u64 | Fixed: schema now enforces `z.number().int()` | -| #114 `confirmationsRequired` accepts fractional values | Fixed: schema now enforces `z.number().int()` | -| #112 `accountProof` nonce accepts non-integers and can crash verifier | Fixed: schema now enforces `z.number().int()` | -| #111 Safe URL parser accepts conflicting Safe addresses in transaction URL | Fixed: address consistency validation added | -| #110 Evidence package `chainId` accepts non-integers | Fixed: schema now enforces `z.number().int()` | -| #109 Evidence package `nonce` accepts non-integers | Fixed: schema now enforces `z.number().int()` | -| #108 Safe API nonce schema accepts non-integers | Fixed: schema now enforces `z.number().int()` | -| #103 Frontend style regression after Tailwind 4 migration | Closed: dependency versions are LTS/stable; CSS entry point migration is a configuration adjustment | ### Replay Status @@ -221,25 +175,33 @@ Snapshot as of **2026-02-24** (synchronized with GitHub issue tracker): | Deterministic mismatch reason codes for replay failures | Implemented | | Replay latency benchmark harness (`p50`/`p95`) | Implemented (`benchmark_replay_latency_profiles`) | -### Resolved In Current Branch - -| Issue | Resolution | -|---|---| -| `fail_result()` dropped accumulated checks in non-beacon envelope verifier | Fixed by returning `fail_result_with_context(...)` for post-envelope validation failures (invalid expected policy root, missing/invalid `packagePackagedAt`). Existing checks and verified envelope context are now preserved. | -| Future-dated envelope timestamp freshness ambiguity | Explicitly rejected when skew exceeds `NON_BEACON_MAX_FUTURE_SKEW_SECS`; covered by regression tests in `consensus.rs`. | -| State-root normalization mismatch risk in envelope verification | Roots are normalized through `parse_b256` + canonical hex formatting before comparison. | - ## External Dependencies | Dependency | Version | Why trusted | Risk | |---|---|---|---| | viem | ^2.x | Standard EVM library, wide adoption, typed | RLP/ABI decoding bugs | -| zod | ^3.x | Schema validation, no network access | Validation bypass | +| zod | ^4.x | Schema validation, no network access | Validation bypass | | helios-consensus-core | (Rust) | a]16z-maintained Ethereum light client | BLS verification bugs | | alloy-primitives | (Rust) | Standard Ethereum types | Type handling bugs | All verification-path dependencies are local-only (no network access). Generation-path additionally uses viem's HTTP transport. +## Auditor Workflow + +Use these as the reviewer baseline: + +1. Run full CI parity checks: + - `bun run verify:ci` +2. Run core package tests: + - `bun test --filter @safelens/core` +3. Run desktop Rust tests: + - `cd apps/desktop/src-tauri && cargo test` + +Expected result: all commands pass without skipped security-critical suites. + +For live issue status, use the canonical tracker: +`https://github.com/Th0rgal/SafeLens/issues` + ## File Map (Security-Critical) ``` diff --git a/docs/architecture/verification-source-contract.md b/docs/architecture/verification-source-contract.md index ac7d1444..24f0ba1d 100644 --- a/docs/architecture/verification-source-contract.md +++ b/docs/architecture/verification-source-contract.md @@ -79,8 +79,9 @@ Desktop UI rule: Notes: -- In witness-only packages, simulation effects are intentionally omitted from - packaged RPC output and are derived from local replay during verification. +- In witness-only packages, replay-complete inputs are attached so simulation + effects can be re-derived locally during verification; packaged simulation + effects are retained for replay/effect comparison. - `simulationWitness.simulationDigest` must always be computed from the exact packaged simulation payload (including witness-only stripped projections). - Desktop `Simulation outcome` must not return a success/check state for From cc4177f488a8532a45de2a9b54aed0a8ca165b89 Mon Sep 17 00:00:00 2001 From: "Thomas Marchand (agent)" Date: Thu, 26 Feb 2026 07:35:51 +0000 Subject: [PATCH 6/9] docs: align trust model and simplify auditor guidance --- AUDIT.md | 55 +++++++++++++++++++++++++++----------------- CONTRIBUTING.md | 10 ++++---- DEPENDENCIES.md | 4 ++-- README.md | 2 +- TRUST_ASSUMPTIONS.md | 23 +++++++++++------- VERIFY.md | 2 +- 6 files changed, 58 insertions(+), 38 deletions(-) diff --git a/AUDIT.md b/AUDIT.md index 097fe212..9072ba00 100644 --- a/AUDIT.md +++ b/AUDIT.md @@ -9,8 +9,8 @@ Four components in a monorepo: | Component | Role | Network access | |---|---|---| | `packages/core` | Shared crypto verification library (TS) | None during verify | -| `apps/generator` | Next.js web app — creates evidence packages | Yes (Safe API, RPC, Beacon) | -| `apps/desktop` | Tauri app — airgapped verification | No external network origins; CSP allows only Tauri IPC (`ipc:` and `http://ipc.localhost`) | +| `apps/generator` | Next.js web app, creates evidence packages | Yes (Safe API, RPC, Beacon) | +| `apps/desktop` | Tauri app, airgapped verification | No external network origins; CSP allows only Tauri IPC (`ipc:` and `http://ipc.localhost`) | | `packages/cli` | CLI wrapper over core | Yes for creation, none for verify | ### Data Flow @@ -28,17 +28,19 @@ User Input (Safe URL/address) → Finalize export contract (fully-verifiable | partial) → Export JSON -Verification (desktop/CLI, offline): +Verification (shared offline checks in CLI and desktop): → Zod schema validation → Recompute safeTxHash from tx fields (CRITICAL: never trust package's hash) → ECDSA signature recovery against recomputed hash → MPT verification of on-chain policy proof against state root → MPT verification of simulation witness anchoring + digest + → Emit trust-classified verification report + +Verification (desktop-only offline checks): → Local `revm` replay of simulation witness world state (desktop path) → Replay witness world state locally and compare replay-derived effects against packaged simulation effects → BLS sync committee verification of consensus proof (Rust/Helios) → Cross-validate: consensus state root == policy proof state root - → Emit trust-classified verification report ``` ## Trust Model @@ -68,7 +70,7 @@ Any failure → stays `rpc-sourced`. See `evaluateConsensusTrustDecision()` in ` ### OP Stack / Linea Trust Boundary -OP Stack and Linea consensus proofs are RPC-sourced execution header reads — **not** independent consensus verification. A compromised RPC can forge both sides. +OP Stack and Linea consensus proofs are RPC-sourced execution header reads, **not** independent consensus verification. A compromised RPC can forge both sides. **Defense**: These modes cannot promote packages to `fully-verifiable`. The creator enforces `hasVerifierSupportedConsensusProof = hasConsensusProofArtifact && proofConsensusMode === "beacon"` (`creator.ts:228-229`). @@ -78,7 +80,7 @@ OP Stack and Linea consensus proofs are RPC-sourced execution header reads — * - **Library**: Helios consensus-core (Rust, `consensus.rs`) - **Algorithm**: BLS12-381 aggregate signatures over beacon block headers -- **Chain**: beacon block root → execution payload root → EVM state root +- **Chain**: beacon block root -> execution payload root -> EVM state root - **Threshold**: >2/3 of 512-member sync committee - **Only finalized headers accepted** - **Fork-aware**: Chain-specific genesis roots and fork schedules bundled @@ -88,11 +90,11 @@ OP Stack and Linea consensus proofs are RPC-sourced execution header reads — * - **Library**: Custom viem-based verifier (`proof/mpt.ts`, `proof/verify-policy.ts`) - **Verifies**: Account proof against state root, storage proofs against storage root - **Safe slots verified**: singleton, owners (linked list), modules (linked list), threshold, nonce, guard, fallback handler -- **Completeness**: Linked list walks are validated (sentinel → items → sentinel) +- **Completeness**: Linked list walks are validated (sentinel -> items -> sentinel) ### ECDSA Signatures -- **Schemes**: `v=27/28` (EIP-712), `v=31/32` (eth_sign wrapped), `v=0/1` (contract/pre-approved, unsupported → warning) +- **Schemes**: `v=27/28` (EIP-712), `v=31/32` (eth_sign wrapped), `v=0/1` (contract/pre-approved, unsupported -> warning) - **Defense**: Always verified against **recomputed** safeTxHash, not the package's claimed hash ### EIP-712 Hashing @@ -103,8 +105,17 @@ OP Stack and Linea consensus proofs are RPC-sourced execution header reads — * ## Attack Surface +### Quick Auditor Read + +- Generation phase: Network is on. Outputs are claims collected from API/RPC/Beacon sources. Mismatch risk is expected here. +- Verification phase: Network is off. The verifier recomputes hashes and checks proofs/signatures locally. +- Not problematic: A generation-time claim differs from local verification and is downgraded to `rpc-sourced` or `api-sourced`. +- Problematic: Verification accepts a claim without required recomputation/proof checks, or upgrades trust when proof/root linkage fails. + ### Generation Phase (network-connected) +This phase is where remote data enters the package. Treat this phase as data collection, not final truth. Data can be malformed or dishonest, so every field that matters must be rechecked in offline verification. + | Input | Validation | Risk | |---|---|---| | Safe URL (user) | Regex parse, Zod schema | Malformed URLs | @@ -116,6 +127,8 @@ OP Stack and Linea consensus proofs are RPC-sourced execution header reads — * ### Verification Phase (airgapped) +This phase is where claims are checked without network access. The verifier recomputes deterministic values and validates proofs. Anything that cannot be independently proven remains explicitly labeled as lower trust. + | Input | Validation | Risk | |---|---|---| | Evidence package JSON | Zod schema | Type confusion, malformed data | @@ -138,14 +151,14 @@ Defense against **hash substitution**: A malicious generator could provide valid ### Why a known private key for simulation? -Simulation uses Hardhat account #0 (`0xac09...ff80`) — universally known and never controls real funds. Safe here because: +Simulation uses Hardhat account #0 (`0xac09...ff80`), universally known and never controls real funds. Safe here because: - Only used in `eth_call` (read-only RPC method) - State overrides plant this as the sole 1-of-1 owner - Never used with `eth_sendRawTransaction` ### Why separate beacon vs non-beacon trust paths? -Beacon light client provides independent cryptographic verification (BLS aggregate signatures from >2/3 of sync committee). OP Stack/Linea envelopes are just RPC header reads — a compromised RPC can forge them. Different trust levels reflect this. +Beacon light client provides independent cryptographic verification (BLS aggregate signatures from >2/3 of sync committee). OP Stack/Linea envelopes are just RPC header reads, and a compromised RPC can forge them. Different trust levels reflect this. ### Why offline verification? @@ -181,7 +194,7 @@ Settings import/export is a local trust boundary (user-supplied JSON parsed by ` |---|---|---|---| | viem | ^2.x | Standard EVM library, wide adoption, typed | RLP/ABI decoding bugs | | zod | ^4.x | Schema validation, no network access | Validation bypass | -| helios-consensus-core | (Rust) | a]16z-maintained Ethereum light client | BLS verification bugs | +| helios-consensus-core | (Rust) | a16z-maintained Ethereum light client | BLS verification bugs | | alloy-primitives | (Rust) | Standard Ethereum types | Type handling bugs | All verification-path dependencies are local-only (no network access). Generation-path additionally uses viem's HTTP transport. @@ -206,16 +219,16 @@ For live issue status, use the canonical tracker: ``` packages/core/src/lib/ - types.ts — Zod schemas (trust boundary definitions) - safe/hash.ts — EIP-712 safeTxHash computation - safe/signatures.ts — ECDSA signature recovery - proof/verify-policy.ts — MPT proof verification - proof/mpt.ts — Merkle Patricia Trie verifier - verify/index.ts — Verification orchestration + trust decisions - package/creator.ts — Evidence package creation + export contract - trust/sources.ts — Trust classification logic - consensus/index.ts — Consensus proof fetching (beacon + execution) + types.ts : Zod schemas (trust boundary definitions) + safe/hash.ts : EIP-712 safeTxHash computation + safe/signatures.ts : ECDSA signature recovery + proof/verify-policy.ts : MPT proof verification + proof/mpt.ts : Merkle Patricia Trie verifier + verify/index.ts : Verification orchestration + trust decisions + package/creator.ts : Evidence package creation + export contract + trust/sources.ts : Trust classification logic + consensus/index.ts : Consensus proof fetching (beacon + execution) apps/desktop/src-tauri/src/ - consensus.rs — BLS verification + non-beacon envelope checks + consensus.rs : BLS verification + non-beacon envelope checks ``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3e7ada1c..25e81095 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,8 +14,8 @@ bun install |------|-------------| | `packages/core` | Shared crypto verification library (TypeScript) | | `packages/cli` | CLI wrapper over core logic | -| `apps/generator` | Next.js web app — creates evidence packages | -| `apps/desktop` | Tauri + Vite desktop app — airgapped verification | +| `apps/generator` | Next.js web app, creates evidence packages | +| `apps/desktop` | Tauri + Vite desktop app, airgapped verification | ## Running Locally @@ -54,6 +54,6 @@ SafeLens is a security tool. Changes to these areas require extra scrutiny: ## Architecture -- [`TRUST_ASSUMPTIONS.md`](TRUST_ASSUMPTIONS.md) — full trust model -- [`AUDIT.md`](AUDIT.md) — security architecture and attack surface -- [`docs/`](docs/) — architecture contracts and runbooks +- [`TRUST_ASSUMPTIONS.md`](TRUST_ASSUMPTIONS.md), full trust model +- [`AUDIT.md`](AUDIT.md), security architecture and attack surface +- [`docs/`](docs/), architecture contracts and runbooks diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 5f5c9169..e781307c 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -4,7 +4,7 @@ Why each dependency exists. Organized by package and split into verification-pat ## Verification Path (security-critical) -These dependencies are in the trust boundary — they handle crypto, schema validation, or EVM execution. +These dependencies are in the trust boundary, they handle crypto, schema validation, or EVM execution. ### packages/core (TypeScript) @@ -76,7 +76,7 @@ These dependencies are not in the verification trust boundary. They handle rende | `next` | ^14.2 | React framework. Serves the generator web app. | | `react` / `react-dom` | ^18.3 | UI rendering. | | `lucide-react` | ^0.454 | Icons. | -| `class-variance-authority` / `clsx` / `tailwind-merge` | — | CSS utilities (same as desktop). | +| `class-variance-authority` / `clsx` / `tailwind-merge` | n/a | CSS utilities (same as desktop). | ### apps/generator (dev) diff --git a/README.md b/README.md index 7e623468..8890e881 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ SafeLens generates and verifies evidence packages for Gnosis Safe multisig trans ## Trust model -The desktop verifier ships with a CSP that restricts `connect-src` to Tauri IPC only (`ipc: http://ipc.localhost`) — no external network origins — and no shell-open capability. It cannot make network requests during verification. All crypto runs locally using bundled libraries. See [`TRUST_ASSUMPTIONS.md`](TRUST_ASSUMPTIONS.md) for the full model. +The desktop verifier ships with a CSP that restricts `connect-src` to Tauri IPC only (`ipc: http://ipc.localhost`), with no external network origins and no shell-open capability. It cannot make network requests during verification. All crypto runs locally using bundled libraries. See [`TRUST_ASSUMPTIONS.md`](TRUST_ASSUMPTIONS.md) for the full model. ## Project docs diff --git a/TRUST_ASSUMPTIONS.md b/TRUST_ASSUMPTIONS.md index fbe5e5f2..d2baf13a 100644 --- a/TRUST_ASSUMPTIONS.md +++ b/TRUST_ASSUMPTIONS.md @@ -4,14 +4,18 @@ This document lists every trust assumption SafeLens makes today. SafeLens classifies each source as: -- `proof-verified`: validated against cryptographic Merkle/consensus proofs +- `consensus-verified-beacon`: state root verified with beacon light-client BLS checks +- `consensus-verified-opstack`: OP Stack envelope integrity verified (not beacon-equivalent) +- `consensus-verified-linea`: Linea envelope integrity verified (not beacon-equivalent) +- `proof-verified`: validated against cryptographic Merkle proofs - `self-verified`: validated locally with deterministic code - `rpc-sourced`: accepted from an RPC endpoint (e.g., generation-time simulation/witness inputs) - `api-sourced`: accepted from remote API responses - `user-provided`: accepted from local operator input or local files Each section of the evidence package carries its own trust classification, -allowing progressive trust upgrades (e.g., `api-sourced` to `proof-verified`) +allowing progressive trust upgrades (e.g., `api-sourced` to `proof-verified`, +or `rpc-sourced` to `consensus-verified-beacon`) as proof infrastructure is added. ## Evidence Generation (`apps/generator`, CLI `analyze`) @@ -33,7 +37,7 @@ as proof infrastructure is added. | Signature scheme coverage | api-sourced when unsupported signatures exist | Contract signatures / pre-approved hashes are not fully verified locally | Use on-chain or Safe-native validation when unsupported signatures appear | | Safe owners and threshold | api-sourced (upgradable to proof-verified) | `confirmations` and `confirmationsRequired` in evidence reflect on-chain state | Include `onchainPolicyProof` to upgrade to proof-verified | | On-chain policy proof | proof-verified when present, disabled otherwise | Merkle storage proofs for owners, threshold, nonce, modules, guard, fallback handler, singleton are valid against provided state root | Verify state root against finalized beacon chain consensus (Phase 4) | -| Transaction simulation | rpc-sourced by default, upgradeable to proof-verified | Generation-time RPC simulation/witness inputs may be wrong until witness and local replay checks pass | Include `simulationWitness` and run desktop replay verification to upgrade simulation trust | +| Transaction simulation | rpc-sourced | Generation-time RPC simulation/witness inputs may be wrong until witness and local replay checks pass | Include `simulationWitness` and run desktop replay verification to prove deterministic consistency against provided witness inputs. Trust remains `rpc-sourced` until replay world-state accounts are fully state-root proven | | Decoded calldata metadata | api-sourced | Human-readable decode (`dataDecoded`) may be incorrect | Treat raw calldata + hash as canonical; decode independently when needed | | Local settings labels | user-provided | Address/contract labels are accurate | Keep settings under change control and review diffs | @@ -56,11 +60,14 @@ without these sections is fully supported and behaves identically to before. From highest to lowest assurance: -1. **proof-verified**: Validated against cryptographic proofs (Merkle storage proofs, consensus proofs) -2. **self-verified**: Validated locally with deterministic code (EIP-712 hash, ECDSA recovery) -3. **rpc-sourced**: Accepted from an RPC endpoint (including generation-time simulation/witness inputs without full local replay confirmation) -4. **api-sourced**: Accepted from a remote API (Safe Transaction Service) -5. **user-provided**: Accepted from local operator input (URLs, settings, timestamps) +1. **consensus-verified-beacon**: State root verified with beacon BLS sync committee checks +2. **consensus-verified-opstack**: OP Stack envelope integrity checks (not beacon-equivalent) +3. **consensus-verified-linea**: Linea envelope integrity checks (not beacon-equivalent) +4. **proof-verified**: Validated against cryptographic Merkle proofs +5. **self-verified**: Validated locally with deterministic code (EIP-712 hash, ECDSA recovery) +6. **rpc-sourced**: Accepted from an RPC endpoint (including generation-time simulation/witness inputs without full local replay confirmation) +7. **api-sourced**: Accepted from a remote API (Safe Transaction Service) +8. **user-provided**: Accepted from local operator input (URLs, settings, timestamps) ## Desktop Airgap Scope diff --git a/VERIFY.md b/VERIFY.md index 70095bfc..9e203b83 100644 --- a/VERIFY.md +++ b/VERIFY.md @@ -76,7 +76,7 @@ Tauri/Rust builds are not yet fully bit-for-bit reproducible across environments - **Timestamps**: Some build tools embed timestamps in binaries - **System libraries**: Linked system libraries (WebKit, OpenSSL) differ across OS versions -The `SHA256SUMS.txt` file in each release is the canonical reference. If you build locally and get a different hash, the above factors are the likely cause — not a supply-chain compromise. The source code itself can always be audited directly. +The `SHA256SUMS.txt` file in each release is the canonical reference. If you build locally and get a different hash, the above factors are the likely cause, not a supply-chain compromise. The source code itself can always be audited directly. ## Reporting Discrepancies From cddd7e3493ad1cbd59869430feb739c42295e6aa Mon Sep 17 00:00:00 2001 From: "Thomas Marchand (agent)" Date: Thu, 26 Feb 2026 07:42:45 +0000 Subject: [PATCH 7/9] docs: align audit and trust docs with runtime behavior --- AUDIT.md | 4 ++-- DEPENDENCIES.md | 2 +- TRUST_ASSUMPTIONS.md | 12 +++++++----- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/AUDIT.md b/AUDIT.md index 9072ba00..0c54afba 100644 --- a/AUDIT.md +++ b/AUDIT.md @@ -122,8 +122,8 @@ This phase is where remote data enters the package. Treat this phase as data col | Safe API response | Zod `safeTransactionSchema` | Malformed payloads | | RPC `eth_getProof` | Zod `accountProofSchema` | Malformed proofs | | RPC `eth_call` | ABI decoding (viem) | Invalid return data | -| Beacon API response | Rust SSZ deserialization | Malformed BLS data | -| Custom RPC URL | URL validation | SSRF (client-side only) | +| Beacon API response | TypeScript parser + Zod schemas (`beacon-api.ts`) | Malformed consensus payloads | +| Custom RPC URL | URL validation and operator-controlled input | Untrusted endpoint input (desktop UI and CLI host context) | ### Verification Phase (airgapped) diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index e781307c..099e2e15 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -111,7 +111,7 @@ helios-consensus-core = { git = "https://github.com/a16z/helios", rev = "582fda3 The pinned commit (`582fda3`, 2026-02-18) includes a fix for hex-encoded `blockNumber` and `chainId` fields in beacon API responses ([helios#776](https://github.com/a16z/helios/pull/776)). The latest tagged Helios release is `0.11.0` (2025-12-16), which does not include this fix. SafeLens needs it because beacon finality update responses from some clients return numeric fields as hex strings. -**Commit provenance:** The commit is on the `main` branch of `a16z/helios`, 17 commits ahead of the `0.11.0` tag. It will be included in the next Helios release. +**Commit provenance:** The commit is on the `main` branch of `a16z/helios`, 17 commits ahead of the `0.11.0` tag. **Action item:** When Helios publishes a release that includes commit `582fda3`, migrate from `rev = "..."` to a version or tag pin. diff --git a/TRUST_ASSUMPTIONS.md b/TRUST_ASSUMPTIONS.md index d2baf13a..b2fd6e29 100644 --- a/TRUST_ASSUMPTIONS.md +++ b/TRUST_ASSUMPTIONS.md @@ -4,6 +4,7 @@ This document lists every trust assumption SafeLens makes today. SafeLens classifies each source as: +- `consensus-verified` (legacy): backward-compatibility enum value for older exports; new reports use mode-specific consensus levels - `consensus-verified-beacon`: state root verified with beacon light-client BLS checks - `consensus-verified-opstack`: OP Stack envelope integrity verified (not beacon-equivalent) - `consensus-verified-linea`: Linea envelope integrity verified (not beacon-equivalent) @@ -63,11 +64,12 @@ From highest to lowest assurance: 1. **consensus-verified-beacon**: State root verified with beacon BLS sync committee checks 2. **consensus-verified-opstack**: OP Stack envelope integrity checks (not beacon-equivalent) 3. **consensus-verified-linea**: Linea envelope integrity checks (not beacon-equivalent) -4. **proof-verified**: Validated against cryptographic Merkle proofs -5. **self-verified**: Validated locally with deterministic code (EIP-712 hash, ECDSA recovery) -6. **rpc-sourced**: Accepted from an RPC endpoint (including generation-time simulation/witness inputs without full local replay confirmation) -7. **api-sourced**: Accepted from a remote API (Safe Transaction Service) -8. **user-provided**: Accepted from local operator input (URLs, settings, timestamps) +4. **consensus-verified** (legacy): Backward-compatibility label from older exports, superseded by mode-specific consensus labels in current output +5. **proof-verified**: Validated against cryptographic Merkle proofs +6. **self-verified**: Validated locally with deterministic code (EIP-712 hash, ECDSA recovery) +7. **rpc-sourced**: Accepted from an RPC endpoint (including generation-time simulation/witness inputs without full local replay confirmation) +8. **api-sourced**: Accepted from a remote API (Safe Transaction Service) +9. **user-provided**: Accepted from local operator input (URLs, settings, timestamps) ## Desktop Airgap Scope From 68f302b8dd457d6783d8c370032e5143dd11f5ac Mon Sep 17 00:00:00 2001 From: "Thomas Marchand (agent)" Date: Thu, 26 Feb 2026 07:50:29 +0000 Subject: [PATCH 8/9] docs(audit): add auditor packet, release integrity, and dependency drift workflow --- .gitignore | 3 + AUDIT.md | 4 + DEPENDENCIES.md | 16 + README.md | 13 + RELEASE_INTEGRITY.md | 44 + SECURITY.md | 20 + VERIFY.md | 16 +- docs/audit/AUDITOR_PACKET.md | 47 + docs/audit/dependency-footprint.baseline.md | 2129 +++++++++++++++++++ docs/audit/dependency-footprint.md | 2129 +++++++++++++++++++ scripts/audit/deps.sh | 68 + 11 files changed, 4488 insertions(+), 1 deletion(-) create mode 100644 RELEASE_INTEGRITY.md create mode 100644 docs/audit/AUDITOR_PACKET.md create mode 100644 docs/audit/dependency-footprint.baseline.md create mode 100644 docs/audit/dependency-footprint.md create mode 100755 scripts/audit/deps.sh diff --git a/.gitignore b/.gitignore index 1de50cf0..cb6130bc 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ next-env.d.ts # screenshots ui-*.png safelens-*.png + +# Generated audit drift output +docs/audit/dependency-footprint.diff diff --git a/AUDIT.md b/AUDIT.md index 0c54afba..abd1d2b5 100644 --- a/AUDIT.md +++ b/AUDIT.md @@ -209,9 +209,13 @@ Use these as the reviewer baseline: - `bun test --filter @safelens/core` 3. Run desktop Rust tests: - `cd apps/desktop/src-tauri && cargo test` +4. Generate dependency footprint and compare drift: + - `bash scripts/audit/deps.sh` Expected result: all commands pass without skipped security-critical suites. +Auditor packet entrypoint: `docs/audit/AUDITOR_PACKET.md`. + For live issue status, use the canonical tracker: `https://github.com/Th0rgal/SafeLens/issues` diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 099e2e15..fe514551 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -2,6 +2,22 @@ Why each dependency exists. Organized by package and split into verification-path (security-critical) vs UI/tooling (non-critical). +## Reviewer workflow + +Generate a dependency snapshot and compare it with the committed baseline: + +```bash +bash scripts/audit/deps.sh +``` + +Artifacts: + +- Current snapshot: `docs/audit/dependency-footprint.md` +- Baseline snapshot: `docs/audit/dependency-footprint.baseline.md` +- Drift diff: `docs/audit/dependency-footprint.diff` + +Any dependency drift should be reviewed together with rationale updates in this file. + ## Verification Path (security-critical) These dependencies are in the trust boundary, they handle crypto, schema validation, or EVM execution. diff --git a/README.md b/README.md index 8890e881..ca681c08 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,24 @@ SafeLens generates and verifies evidence packages for Gnosis Safe multisig trans The desktop verifier ships with a CSP that restricts `connect-src` to Tauri IPC only (`ipc: http://ipc.localhost`), with no external network origins and no shell-open capability. It cannot make network requests during verification. All crypto runs locally using bundled libraries. See [`TRUST_ASSUMPTIONS.md`](TRUST_ASSUMPTIONS.md) for the full model. +## Independent verification stack + +SafeLens is one verifier in a multi-tool workflow, not a single source of truth. + +- Tool 1: Independent Safe hash verifiers (for example `safe-tx-hashes-util`) validate digest expectations. +- Tool 2: Hardware wallet screen validates the hash shown at signing time. +- Tool 3: Foundry or local node simulation validates execution expectations. +- Tool 4: SafeLens validates offline package integrity, signatures, and optional proofs. + +For high-value operations, use at least two independent tools and compare outputs. + ## Project docs - Security policy: [`SECURITY.md`](SECURITY.md) - Contributing guidelines: [`CONTRIBUTING.md`](CONTRIBUTING.md) - Build verification: [`VERIFY.md`](VERIFY.md) +- Release integrity checks: [`RELEASE_INTEGRITY.md`](RELEASE_INTEGRITY.md) +- Auditor packet: [`docs/audit/AUDITOR_PACKET.md`](docs/audit/AUDITOR_PACKET.md) ## Architecture and runbooks diff --git a/RELEASE_INTEGRITY.md b/RELEASE_INTEGRITY.md new file mode 100644 index 00000000..3598d5bc --- /dev/null +++ b/RELEASE_INTEGRITY.md @@ -0,0 +1,44 @@ +# Release Integrity + +This document defines the reviewer workflow for release integrity checks. + +## Policy + +- Release tags (`v*`) are treated as immutable once published. +- Release artifacts are tied to a specific git tag and commit. +- Release checksums in `SHA256SUMS.txt` are the canonical artifact integrity record. + +## Verify Tag to Commit + +```bash +git fetch --tags origin +git show --no-patch --pretty=fuller v0.4.0 +git rev-list -n 1 v0.4.0 +``` + +Expected result: the tag resolves to the intended audited commit. + +## Verify Artifact Checksums + +```bash +# Example on Linux/macOS +sha256sum SafeLens_0.4.0_aarch64.dmg +# Compare with matching line in SHA256SUMS.txt +``` + +```powershell +# Example on Windows +Get-FileHash SafeLens_0.4.0_x64-setup.exe -Algorithm SHA256 +``` + +Expected result: local checksum equals the value in `SHA256SUMS.txt`. + +## Verify CI Workflow Source + +Release pipeline definition: +- `.github/workflows/release.yml` + +Test/CI parity pipeline definition: +- `.github/workflows/test.yml` + +Expected result: pinned action revisions, pinned Bun and Rust versions, and `bun install --frozen-lockfile` in CI. diff --git a/SECURITY.md b/SECURITY.md index 03298b84..cc2e305e 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -51,3 +51,23 @@ Out of scope: ## Trust Model See [`TRUST_ASSUMPTIONS.md`](TRUST_ASSUMPTIONS.md) for the full trust model and [`AUDIT.md`](AUDIT.md) for the security architecture. + +## Threat Model Summary + +### Protects against + +| Scenario | Condition | +|---|---| +| Malicious or incorrect Safe API payload | Offline verifier recomputes safeTxHash and checks signatures | +| Hash substitution in exported evidence | Claimed hash is never trusted, verifier recomputes from transaction fields | +| Malformed policy proof artifacts | MPT proofs are validated locally before trust upgrades | +| Desktop data exfiltration during verification | CSP and Tauri config block external network access | + +### Does not protect against + +| Scenario | Reason | +|---|---| +| Compromised airgapped machine | Local runtime and OS are in the trusted computing base | +| Compromised RPC used during generation | Generation is network-connected and treated as untrusted input collection | +| Compromised Foundry/local node simulation tooling | External simulation tools are out of SafeLens trust boundary | +| Unsupported signature schemes fully verified offline | Some signature modes require on-chain validation and are reported as warnings | diff --git a/VERIFY.md b/VERIFY.md index 9e203b83..8dcbe9c0 100644 --- a/VERIFY.md +++ b/VERIFY.md @@ -2,6 +2,8 @@ How to confirm that a released binary matches the source code. +For release integrity policy and immutable tag checks, see [`RELEASE_INTEGRITY.md`](RELEASE_INTEGRITY.md). + ## Checksum Verification Every [GitHub release](https://github.com/Th0rgal/SafeLens/releases) includes a `SHA256SUMS.txt` file listing the SHA-256 hash of each artifact. @@ -68,6 +70,18 @@ Release builds run in GitHub Actions ([`release.yml`](.github/workflows/release. All CI runners use the same pinned toolchain versions (Bun 1.3.9, Rust 1.93.1) and `--frozen-lockfile` to ensure deterministic dependency resolution. +## Tag and Release Integrity + +Before trusting a release artifact, verify the release tag points to the expected commit: + +```bash +git fetch --tags origin +git rev-list -n 1 v0.4.0 +git rev-parse origin/main +``` + +Then verify the published artifact checksum against `SHA256SUMS.txt`. + ## Reproducibility Limitations Tauri/Rust builds are not yet fully bit-for-bit reproducible across environments due to: @@ -76,7 +90,7 @@ Tauri/Rust builds are not yet fully bit-for-bit reproducible across environments - **Timestamps**: Some build tools embed timestamps in binaries - **System libraries**: Linked system libraries (WebKit, OpenSSL) differ across OS versions -The `SHA256SUMS.txt` file in each release is the canonical reference. If you build locally and get a different hash, the above factors are the likely cause, not a supply-chain compromise. The source code itself can always be audited directly. +The `SHA256SUMS.txt` file in each release is the canonical reference. If local hashes differ, investigate code signing, timestamps, and system library differences before drawing conclusions. ## Reporting Discrepancies diff --git a/docs/audit/AUDITOR_PACKET.md b/docs/audit/AUDITOR_PACKET.md new file mode 100644 index 00000000..484672fb --- /dev/null +++ b/docs/audit/AUDITOR_PACKET.md @@ -0,0 +1,47 @@ +# Auditor Packet + +Single entrypoint for reviewers who need fast, reproducible validation. + +## Required docs + +- `AUDIT.md` +- `TRUST_ASSUMPTIONS.md` +- `DEPENDENCIES.md` +- `VERIFY.md` +- `RELEASE_INTEGRITY.md` + +## Quick verification commands + +Run from repository root: + +```bash +bun install --frozen-lockfile +bun run verify:ci +bun test --filter @safelens/core +cargo test --manifest-path apps/desktop/src-tauri/Cargo.toml +bash scripts/audit/deps.sh +``` + +Expected result: all commands pass and `docs/audit/dependency-footprint.md` is generated. + +## Trust-level interpretation + +- `self-verified`: local deterministic checks passed. +- `proof-verified`: MPT proof checks passed. +- `consensus-verified-beacon`: beacon light-client checks passed. +- `consensus-verified-opstack` / `consensus-verified-linea`: deterministic envelope checks only, not beacon-equivalent. +- `rpc-sourced` / `api-sourced`: input accepted but not fully upgraded by independent proof checks. + +## Review focus + +- Verify trust upgrades only occur when all required proofs and root linkage checks pass. +- Verify any unsupported signature mode is clearly downgraded and surfaced as warning. +- Verify desktop verification remains airgapped (no external network calls). + +## Dependency drift review + +- Current snapshot: `docs/audit/dependency-footprint.md` +- Baseline snapshot: `docs/audit/dependency-footprint.baseline.md` +- Drift output: `docs/audit/dependency-footprint.diff` + +If drift exists, require explicit rationale updates in `DEPENDENCIES.md`. diff --git a/docs/audit/dependency-footprint.baseline.md b/docs/audit/dependency-footprint.baseline.md new file mode 100644 index 00000000..87837d1b --- /dev/null +++ b/docs/audit/dependency-footprint.baseline.md @@ -0,0 +1,2129 @@ +# Dependency Footprint + +Generated by `scripts/audit/deps.sh`. + +## Inputs + +- `bun.lock` SHA-256: `d78b3a1b2e6d6daa607f8d711bffaef2e74e639c7eff66bd05c12dc2de6aeb0f` +- `apps/desktop/src-tauri/Cargo.lock`: `present` + +## JavaScript Dependency Tree (bun list --all) + +```text +/workspaces/mission-b3dce69f/repo node_modules +├── @adraffy/ens-normalize@1.11.1 +├── @alloc/quick-lru@5.2.0 +├── @babel/code-frame@7.29.0 +├── @babel/compat-data@7.29.0 +├── @babel/core@7.29.0 +├── @babel/generator@7.29.1 +├── @babel/helper-compilation-targets@7.28.6 +├── @babel/helper-globals@7.28.0 +├── @babel/helper-module-imports@7.28.6 +├── @babel/helper-module-transforms@7.28.6 +├── @babel/helper-plugin-utils@7.28.6 +├── @babel/helper-string-parser@7.27.1 +├── @babel/helper-validator-identifier@7.28.5 +├── @babel/helper-validator-option@7.27.1 +├── @babel/helpers@7.28.6 +├── @babel/parser@7.29.0 +├── @babel/plugin-transform-react-jsx-self@7.27.1 +├── @babel/plugin-transform-react-jsx-source@7.27.1 +├── @babel/template@7.28.6 +├── @babel/traverse@7.29.0 +├── @babel/types@7.29.0 +├── @emnapi/core@1.8.1 +├── @emnapi/runtime@1.8.1 +├── @emnapi/wasi-threads@1.1.0 +├── @esbuild/aix-ppc64@0.21.5 +├── @esbuild/android-arm@0.21.5 +├── @esbuild/android-arm64@0.21.5 +├── @esbuild/android-x64@0.21.5 +├── @esbuild/darwin-arm64@0.21.5 +├── @esbuild/darwin-x64@0.21.5 +├── @esbuild/freebsd-arm64@0.21.5 +├── @esbuild/freebsd-x64@0.21.5 +├── @esbuild/linux-arm@0.21.5 +├── @esbuild/linux-arm64@0.21.5 +├── @esbuild/linux-ia32@0.21.5 +├── @esbuild/linux-loong64@0.21.5 +├── @esbuild/linux-mips64el@0.21.5 +├── @esbuild/linux-ppc64@0.21.5 +├── @esbuild/linux-riscv64@0.21.5 +├── @esbuild/linux-s390x@0.21.5 +├── @esbuild/linux-x64@0.21.5 +├── @esbuild/netbsd-arm64@0.27.3 +├── @esbuild/netbsd-x64@0.21.5 +├── @esbuild/openbsd-arm64@0.27.3 +├── @esbuild/openbsd-x64@0.21.5 +├── @esbuild/openharmony-arm64@0.27.3 +├── @esbuild/sunos-x64@0.21.5 +├── @esbuild/win32-arm64@0.21.5 +├── @esbuild/win32-ia32@0.21.5 +├── @esbuild/win32-x64@0.21.5 +├── @eslint-community/eslint-utils@4.9.1 +├── @eslint-community/regexpp@4.12.2 +├── @eslint/eslintrc@2.1.4 +├── @eslint/js@8.57.1 +├── @humanwhocodes/config-array@0.13.0 +├── @humanwhocodes/module-importer@1.0.1 +├── @humanwhocodes/object-schema@2.0.3 +├── @isaacs/cliui@8.0.2 +│ └── strip-ansi@7.1.2 +│ └── ansi-regex@6.2.2 +├── @jridgewell/gen-mapping@0.3.13 +├── @jridgewell/remapping@2.3.5 +├── @jridgewell/resolve-uri@3.1.2 +├── @jridgewell/sourcemap-codec@1.5.5 +├── @jridgewell/trace-mapping@0.3.31 +├── @napi-rs/wasm-runtime@0.2.12 +├── @next/env@14.2.35 +├── @next/eslint-plugin-next@14.2.35 +├── @next/swc-darwin-arm64@14.2.33 +├── @next/swc-darwin-x64@14.2.33 +├── @next/swc-linux-arm64-gnu@14.2.33 +├── @next/swc-linux-arm64-musl@14.2.33 +├── @next/swc-linux-x64-gnu@14.2.33 +├── @next/swc-linux-x64-musl@14.2.33 +├── @next/swc-win32-arm64-msvc@14.2.33 +├── @next/swc-win32-ia32-msvc@14.2.33 +├── @next/swc-win32-x64-msvc@14.2.33 +├── @noble/ciphers@1.3.0 +├── @noble/curves@1.9.1 +├── @noble/hashes@1.8.0 +├── @nodelib/fs.scandir@2.1.5 +├── @nodelib/fs.stat@2.0.5 +├── @nodelib/fs.walk@1.2.8 +├── @nolyfill/is-core-module@1.0.39 +├── @pkgjs/parseargs@0.11.0 +├── @rolldown/pluginutils@1.0.0-beta.27 +├── @rollup/rollup-android-arm-eabi@4.57.1 +├── @rollup/rollup-android-arm64@4.57.1 +├── @rollup/rollup-darwin-arm64@4.57.1 +├── @rollup/rollup-darwin-x64@4.57.1 +├── @rollup/rollup-freebsd-arm64@4.57.1 +├── @rollup/rollup-freebsd-x64@4.57.1 +├── @rollup/rollup-linux-arm-gnueabihf@4.57.1 +├── @rollup/rollup-linux-arm-musleabihf@4.57.1 +├── @rollup/rollup-linux-arm64-gnu@4.57.1 +├── @rollup/rollup-linux-arm64-musl@4.57.1 +├── @rollup/rollup-linux-loong64-gnu@4.57.1 +├── @rollup/rollup-linux-loong64-musl@4.57.1 +├── @rollup/rollup-linux-ppc64-gnu@4.57.1 +├── @rollup/rollup-linux-ppc64-musl@4.57.1 +├── @rollup/rollup-linux-riscv64-gnu@4.57.1 +├── @rollup/rollup-linux-riscv64-musl@4.57.1 +├── @rollup/rollup-linux-s390x-gnu@4.57.1 +├── @rollup/rollup-linux-x64-gnu@4.57.1 +├── @rollup/rollup-linux-x64-musl@4.57.1 +├── @rollup/rollup-openbsd-x64@4.57.1 +├── @rollup/rollup-openharmony-arm64@4.57.1 +├── @rollup/rollup-win32-arm64-msvc@4.57.1 +├── @rollup/rollup-win32-ia32-msvc@4.57.1 +├── @rollup/rollup-win32-x64-gnu@4.57.1 +├── @rollup/rollup-win32-x64-msvc@4.57.1 +├── @rtsao/scc@1.1.0 +├── @rushstack/eslint-patch@1.16.1 +├── @safelens/cli@workspace:packages/cli +├── @safelens/core@workspace:packages/core +├── @safelens/desktop@workspace:apps/desktop +├── @safelens/generator@workspace:apps/generator +│ └── @types/node@20.19.33 +│ └── undici-types@6.21.0 +├── @safelens/shared-theme@workspace:apps/shared-theme +├── @scure/base@1.2.6 +├── @scure/bip32@1.7.0 +├── @scure/bip39@1.6.0 +├── @standard-schema/spec@1.1.0 +├── @swc/counter@0.1.3 +├── @swc/helpers@0.5.5 +├── @tauri-apps/api@2.10.1 +├── @tauri-apps/cli@2.10.0 +├── @tauri-apps/cli-darwin-arm64@2.10.0 +├── @tauri-apps/cli-darwin-x64@2.10.0 +├── @tauri-apps/cli-linux-arm-gnueabihf@2.10.0 +├── @tauri-apps/cli-linux-arm64-gnu@2.10.0 +├── @tauri-apps/cli-linux-arm64-musl@2.10.0 +├── @tauri-apps/cli-linux-riscv64-gnu@2.10.0 +├── @tauri-apps/cli-linux-x64-gnu@2.10.0 +├── @tauri-apps/cli-linux-x64-musl@2.10.0 +├── @tauri-apps/cli-win32-arm64-msvc@2.10.0 +├── @tauri-apps/cli-win32-ia32-msvc@2.10.0 +├── @tauri-apps/cli-win32-x64-msvc@2.10.0 +├── @tauri-apps/plugin-dialog@2.6.0 +├── @tauri-apps/plugin-fs@2.4.5 +├── @tybys/wasm-util@0.10.1 +├── @types/babel__core@7.20.5 +├── @types/babel__generator@7.27.0 +├── @types/babel__template@7.4.4 +├── @types/babel__traverse@7.28.0 +├── @types/chai@5.2.3 +├── @types/deep-eql@4.0.2 +├── @types/estree@1.0.8 +├── @types/json5@0.0.29 +├── @types/node@25.3.0 +├── @types/prop-types@15.7.15 +├── @types/react@18.3.28 +├── @types/react-dom@18.3.7 +├── @typescript-eslint/eslint-plugin@8.56.0 +│ └── ignore@7.0.5 +├── @typescript-eslint/parser@8.56.0 +├── @typescript-eslint/project-service@8.56.0 +├── @typescript-eslint/scope-manager@8.56.0 +├── @typescript-eslint/tsconfig-utils@8.56.0 +├── @typescript-eslint/type-utils@8.56.0 +├── @typescript-eslint/types@8.56.0 +├── @typescript-eslint/typescript-estree@8.56.0 +│ ├── minimatch@9.0.5 +│ │ └── brace-expansion@2.0.2 +│ └── semver@7.7.4 +├── @typescript-eslint/utils@8.56.0 +├── @typescript-eslint/visitor-keys@8.56.0 +│ └── eslint-visitor-keys@5.0.1 +├── @ungap/structured-clone@1.3.0 +├── @unrs/resolver-binding-android-arm-eabi@1.11.1 +├── @unrs/resolver-binding-android-arm64@1.11.1 +├── @unrs/resolver-binding-darwin-arm64@1.11.1 +├── @unrs/resolver-binding-darwin-x64@1.11.1 +├── @unrs/resolver-binding-freebsd-x64@1.11.1 +├── @unrs/resolver-binding-linux-arm-gnueabihf@1.11.1 +├── @unrs/resolver-binding-linux-arm-musleabihf@1.11.1 +├── @unrs/resolver-binding-linux-arm64-gnu@1.11.1 +├── @unrs/resolver-binding-linux-arm64-musl@1.11.1 +├── @unrs/resolver-binding-linux-ppc64-gnu@1.11.1 +├── @unrs/resolver-binding-linux-riscv64-gnu@1.11.1 +├── @unrs/resolver-binding-linux-riscv64-musl@1.11.1 +├── @unrs/resolver-binding-linux-s390x-gnu@1.11.1 +├── @unrs/resolver-binding-linux-x64-gnu@1.11.1 +├── @unrs/resolver-binding-linux-x64-musl@1.11.1 +├── @unrs/resolver-binding-wasm32-wasi@1.11.1 +├── @unrs/resolver-binding-win32-arm64-msvc@1.11.1 +├── @unrs/resolver-binding-win32-ia32-msvc@1.11.1 +├── @unrs/resolver-binding-win32-x64-msvc@1.11.1 +├── @vitejs/plugin-react@4.7.0 +├── @vitest/expect@4.0.18 +├── @vitest/mocker@4.0.18 +│ └── vite@7.3.1 +│ └── esbuild@0.27.3 +│ ├── @esbuild/aix-ppc64@0.27.3 +│ ├── @esbuild/android-arm@0.27.3 +│ ├── @esbuild/android-arm64@0.27.3 +│ ├── @esbuild/android-x64@0.27.3 +│ ├── @esbuild/darwin-arm64@0.27.3 +│ ├── @esbuild/darwin-x64@0.27.3 +│ ├── @esbuild/freebsd-arm64@0.27.3 +│ ├── @esbuild/freebsd-x64@0.27.3 +│ ├── @esbuild/linux-arm@0.27.3 +│ ├── @esbuild/linux-arm64@0.27.3 +│ ├── @esbuild/linux-ia32@0.27.3 +│ ├── @esbuild/linux-loong64@0.27.3 +│ ├── @esbuild/linux-mips64el@0.27.3 +│ ├── @esbuild/linux-ppc64@0.27.3 +│ ├── @esbuild/linux-riscv64@0.27.3 +│ ├── @esbuild/linux-s390x@0.27.3 +│ ├── @esbuild/linux-x64@0.27.3 +│ ├── @esbuild/netbsd-x64@0.27.3 +│ ├── @esbuild/openbsd-x64@0.27.3 +│ ├── @esbuild/sunos-x64@0.27.3 +│ ├── @esbuild/win32-arm64@0.27.3 +│ ├── @esbuild/win32-ia32@0.27.3 +│ └── @esbuild/win32-x64@0.27.3 +├── @vitest/pretty-format@4.0.18 +├── @vitest/runner@4.0.18 +├── @vitest/snapshot@4.0.18 +├── @vitest/spy@4.0.18 +├── @vitest/utils@4.0.18 +├── abitype@1.2.3 +├── acorn@8.16.0 +├── acorn-jsx@5.3.2 +├── ajv@6.12.6 +├── ansi-regex@5.0.1 +├── ansi-styles@4.3.0 +├── any-promise@1.3.0 +├── anymatch@3.1.3 +│ └── picomatch@2.3.1 +├── arg@5.0.2 +├── argparse@2.0.1 +├── aria-query@5.3.2 +├── array-buffer-byte-length@1.0.2 +├── array-includes@3.1.9 +├── array.prototype.findlast@1.2.5 +├── array.prototype.findlastindex@1.2.6 +├── array.prototype.flat@1.3.3 +├── array.prototype.flatmap@1.3.3 +├── array.prototype.tosorted@1.1.4 +├── arraybuffer.prototype.slice@1.0.4 +├── assertion-error@2.0.1 +├── ast-types-flow@0.0.8 +├── async-function@1.0.0 +├── autoprefixer@10.4.24 +├── available-typed-arrays@1.0.7 +├── axe-core@4.11.1 +├── axobject-query@4.1.0 +├── balanced-match@1.0.2 +├── baseline-browser-mapping@2.9.19 +├── binary-extensions@2.3.0 +├── brace-expansion@1.1.12 +├── braces@3.0.3 +├── browserslist@4.28.1 +├── busboy@1.6.0 +├── call-bind@1.0.8 +├── call-bind-apply-helpers@1.0.2 +├── call-bound@1.0.4 +├── callsites@3.1.0 +├── camelcase-css@2.0.1 +├── caniuse-lite@1.0.30001769 +├── chai@6.2.2 +├── chalk@4.1.2 +├── chokidar@3.6.0 +│ └── glob-parent@5.1.2 +├── class-variance-authority@0.7.1 +├── client-only@0.0.1 +├── clsx@2.1.1 +├── color-convert@2.0.1 +├── color-name@1.1.4 +├── commander@4.1.1 +├── concat-map@0.0.1 +├── convert-source-map@2.0.0 +├── cross-spawn@7.0.6 +├── cssesc@3.0.0 +├── csstype@3.2.3 +├── damerau-levenshtein@1.0.8 +├── data-view-buffer@1.0.2 +├── data-view-byte-length@1.0.2 +├── data-view-byte-offset@1.0.1 +├── debug@4.4.3 +├── deep-is@0.1.4 +├── define-data-property@1.1.4 +├── define-properties@1.2.1 +├── detect-libc@2.1.2 +├── didyoumean@1.2.2 +├── dlv@1.1.3 +├── doctrine@3.0.0 +├── dunder-proto@1.0.1 +├── eastasianwidth@0.2.0 +├── electron-to-chromium@1.5.286 +├── emoji-regex@9.2.2 +├── es-abstract@1.24.1 +├── es-define-property@1.0.1 +├── es-errors@1.3.0 +├── es-iterator-helpers@1.2.2 +├── es-module-lexer@1.7.0 +├── es-object-atoms@1.1.1 +├── es-set-tostringtag@2.1.0 +├── es-shim-unscopables@1.1.0 +├── es-to-primitive@1.3.0 +├── esbuild@0.21.5 +├── escalade@3.2.0 +├── escape-string-regexp@4.0.0 +├── eslint@8.57.1 +├── eslint-config-next@14.2.35 +├── eslint-import-resolver-node@0.3.9 +│ └── debug@3.2.7 +├── eslint-import-resolver-typescript@3.10.1 +├── eslint-module-utils@2.12.1 +│ └── debug@3.2.7 +├── eslint-plugin-import@2.32.0 +│ ├── debug@3.2.7 +│ └── doctrine@2.1.0 +├── eslint-plugin-jsx-a11y@6.10.2 +├── eslint-plugin-react@7.37.5 +│ ├── doctrine@2.1.0 +│ └── resolve@2.0.0-next.5 +├── eslint-plugin-react-hooks@4.6.2 +├── eslint-scope@7.2.2 +├── eslint-visitor-keys@3.4.3 +├── espree@9.6.1 +├── esquery@1.7.0 +├── esrecurse@4.3.0 +├── estraverse@5.3.0 +├── estree-walker@3.0.3 +├── esutils@2.0.3 +├── eventemitter3@5.0.1 +├── expect-type@1.3.0 +├── fast-deep-equal@3.1.3 +├── fast-glob@3.3.3 +│ └── glob-parent@5.1.2 +├── fast-json-stable-stringify@2.1.0 +├── fast-levenshtein@2.0.6 +├── fastq@1.20.1 +├── fdir@6.5.0 +├── file-entry-cache@6.0.1 +├── fill-range@7.1.1 +├── find-up@5.0.0 +├── flat-cache@3.2.0 +├── flatted@3.3.3 +├── for-each@0.3.5 +├── foreground-child@3.3.1 +├── fraction.js@5.3.4 +├── fs.realpath@1.0.0 +├── fsevents@2.3.3 +├── function-bind@1.1.2 +├── function.prototype.name@1.1.8 +├── functions-have-names@1.2.3 +├── generator-function@2.0.1 +├── gensync@1.0.0-beta.2 +├── get-intrinsic@1.3.0 +├── get-proto@1.0.1 +├── get-symbol-description@1.1.0 +├── get-tsconfig@4.13.6 +├── glob@10.3.10 +│ └── minimatch@9.0.5 +│ └── brace-expansion@2.0.2 +├── glob-parent@6.0.2 +├── globals@13.24.0 +├── globalthis@1.0.4 +├── gopd@1.2.0 +├── graceful-fs@4.2.11 +├── graphemer@1.4.0 +├── has-bigints@1.1.0 +├── has-flag@4.0.0 +├── has-property-descriptors@1.0.2 +├── has-proto@1.2.0 +├── has-symbols@1.1.0 +├── has-tostringtag@1.0.2 +├── hasown@2.0.2 +├── ignore@5.3.2 +├── import-fresh@3.3.1 +├── imurmurhash@0.1.4 +├── inflight@1.0.6 +├── inherits@2.0.4 +├── internal-slot@1.1.0 +├── is-array-buffer@3.0.5 +├── is-async-function@2.1.1 +├── is-bigint@1.1.0 +├── is-binary-path@2.1.0 +├── is-boolean-object@1.2.2 +├── is-bun-module@2.0.0 +│ └── semver@7.7.4 +├── is-callable@1.2.7 +├── is-core-module@2.16.1 +├── is-data-view@1.0.2 +├── is-date-object@1.1.0 +├── is-extglob@2.1.1 +├── is-finalizationregistry@1.1.1 +├── is-fullwidth-code-point@3.0.0 +├── is-generator-function@1.1.2 +├── is-glob@4.0.3 +├── is-map@2.0.3 +├── is-negative-zero@2.0.3 +├── is-number@7.0.0 +├── is-number-object@1.1.1 +├── is-path-inside@3.0.3 +├── is-regex@1.2.1 +├── is-set@2.0.3 +├── is-shared-array-buffer@1.0.4 +├── is-string@1.1.1 +├── is-symbol@1.1.1 +├── is-typed-array@1.1.15 +├── is-weakmap@2.0.2 +├── is-weakref@1.1.1 +├── is-weakset@2.0.4 +├── isarray@2.0.5 +├── isexe@2.0.0 +├── isows@1.0.7 +├── iterator.prototype@1.1.5 +├── jackspeak@2.3.6 +├── jiti@1.21.7 +├── js-tokens@4.0.0 +├── js-yaml@4.1.1 +├── jsesc@3.1.0 +├── json-buffer@3.0.1 +├── json-schema-traverse@0.4.1 +├── json-stable-stringify-without-jsonify@1.0.1 +├── json5@2.2.3 +├── jsx-ast-utils@3.3.5 +├── keyv@4.5.4 +├── language-subtag-registry@0.3.23 +├── language-tags@1.0.9 +├── levn@0.4.1 +├── lightningcss@1.31.1 +├── lightningcss-android-arm64@1.31.1 +├── lightningcss-darwin-arm64@1.31.1 +├── lightningcss-darwin-x64@1.31.1 +├── lightningcss-freebsd-x64@1.31.1 +├── lightningcss-linux-arm-gnueabihf@1.31.1 +├── lightningcss-linux-arm64-gnu@1.31.1 +├── lightningcss-linux-arm64-musl@1.31.1 +├── lightningcss-linux-x64-gnu@1.31.1 +├── lightningcss-linux-x64-musl@1.31.1 +├── lightningcss-win32-arm64-msvc@1.31.1 +├── lightningcss-win32-x64-msvc@1.31.1 +├── lilconfig@3.1.3 +├── lines-and-columns@1.2.4 +├── locate-path@6.0.0 +├── lodash.merge@4.6.2 +├── loose-envify@1.4.0 +├── lru-cache@5.1.1 +├── lucide-react@0.454.0 +├── magic-string@0.30.21 +├── math-intrinsics@1.1.0 +├── merge2@1.4.1 +├── micromatch@4.0.8 +│ └── picomatch@2.3.1 +├── minimatch@3.1.2 +├── minimist@1.2.8 +├── minipass@7.1.3 +├── ms@2.1.3 +├── mz@2.7.0 +├── nanoid@3.3.11 +├── napi-postinstall@0.3.4 +├── natural-compare@1.4.0 +├── next@14.2.35 +│ └── postcss@8.4.31 +├── node-releases@2.0.27 +├── normalize-path@3.0.0 +├── object-assign@4.1.1 +├── object-hash@3.0.0 +├── object-inspect@1.13.4 +├── object-keys@1.1.1 +├── object.assign@4.1.7 +├── object.entries@1.1.9 +├── object.fromentries@2.0.8 +├── object.groupby@1.0.3 +├── object.values@1.2.1 +├── obug@2.1.1 +├── once@1.4.0 +├── optionator@0.9.4 +├── own-keys@1.0.1 +├── ox@0.12.1 +├── p-limit@3.1.0 +├── p-locate@5.0.0 +├── parent-module@1.0.1 +├── path-exists@4.0.0 +├── path-is-absolute@1.0.1 +├── path-key@3.1.1 +├── path-parse@1.0.7 +├── path-scurry@1.11.1 +│ └── lru-cache@10.4.3 +├── pathe@2.0.3 +├── picocolors@1.1.1 +├── picomatch@4.0.3 +├── pify@2.3.0 +├── pirates@4.0.7 +├── possible-typed-array-names@1.1.0 +├── postcss@8.5.6 +├── postcss-import@15.1.0 +├── postcss-js@4.1.0 +├── postcss-load-config@6.0.1 +├── postcss-nested@6.2.0 +├── postcss-selector-parser@6.1.2 +├── postcss-value-parser@4.2.0 +├── prelude-ls@1.2.1 +├── prop-types@15.8.1 +├── punycode@2.3.1 +├── queue-microtask@1.2.3 +├── react@18.3.1 +├── react-dom@18.3.1 +├── react-is@16.13.1 +├── react-refresh@0.17.0 +├── read-cache@1.0.0 +├── readdirp@3.6.0 +│ └── picomatch@2.3.1 +├── reflect.getprototypeof@1.0.10 +├── regexp.prototype.flags@1.5.4 +├── resolve@1.22.11 +├── resolve-from@4.0.0 +├── resolve-pkg-maps@1.0.0 +├── reusify@1.1.0 +├── rimraf@3.0.2 +│ └── glob@7.2.3 +├── rollup@4.57.1 +├── run-parallel@1.2.0 +├── safe-array-concat@1.1.3 +├── safe-push-apply@1.0.0 +├── safe-regex-test@1.1.0 +├── scheduler@0.23.2 +├── semver@6.3.1 +├── set-function-length@1.2.2 +├── set-function-name@2.0.2 +├── set-proto@1.0.0 +├── shebang-command@2.0.0 +├── shebang-regex@3.0.0 +├── side-channel@1.1.0 +├── side-channel-list@1.0.0 +├── side-channel-map@1.0.1 +├── side-channel-weakmap@1.0.2 +├── siginfo@2.0.0 +├── signal-exit@4.1.0 +├── source-map-js@1.2.1 +├── stable-hash@0.0.5 +├── stackback@0.0.2 +├── std-env@3.10.0 +├── stop-iteration-iterator@1.1.0 +├── streamsearch@1.1.0 +├── string-width@5.1.2 +│ └── strip-ansi@7.1.2 +│ └── ansi-regex@6.2.2 +├── string-width-cjs@4.2.3 +│ └── emoji-regex@8.0.0 +├── string.prototype.includes@2.0.1 +├── string.prototype.matchall@4.0.12 +├── string.prototype.repeat@1.0.0 +├── string.prototype.trim@1.2.10 +├── string.prototype.trimend@1.0.9 +├── string.prototype.trimstart@1.0.8 +├── strip-ansi@6.0.1 +├── strip-ansi-cjs@6.0.1 +├── strip-bom@3.0.0 +├── strip-json-comments@3.1.1 +├── styled-jsx@5.1.1 +├── sucrase@3.35.1 +├── supports-color@7.2.0 +├── supports-preserve-symlinks-flag@1.0.0 +├── tailwind-merge@2.6.1 +├── tailwindcss@3.4.19 +├── text-table@0.2.0 +├── thenify@3.3.1 +├── thenify-all@1.6.0 +├── tinybench@2.9.0 +├── tinyexec@1.0.2 +├── tinyglobby@0.2.15 +├── tinyrainbow@3.0.3 +├── to-regex-range@5.0.1 +├── ts-api-utils@2.4.0 +├── ts-interface-checker@0.1.13 +├── tsconfig-paths@3.15.0 +│ └── json5@1.0.2 +├── tslib@2.8.1 +├── type-check@0.4.0 +├── type-fest@0.20.2 +├── typed-array-buffer@1.0.3 +├── typed-array-byte-length@1.0.3 +├── typed-array-byte-offset@1.0.4 +├── typed-array-length@1.0.7 +├── typescript@5.9.3 +├── unbox-primitive@1.1.0 +├── undici-types@7.18.2 +├── unrs-resolver@1.11.1 +├── update-browserslist-db@1.2.3 +├── uri-js@4.4.1 +├── util-deprecate@1.0.2 +├── viem@2.45.3 +├── vite@5.4.21 +├── vitest@4.0.18 +│ └── vite@7.3.1 +│ └── esbuild@0.27.3 +│ ├── @esbuild/aix-ppc64@0.27.3 +│ ├── @esbuild/android-arm@0.27.3 +│ ├── @esbuild/android-arm64@0.27.3 +│ ├── @esbuild/android-x64@0.27.3 +│ ├── @esbuild/darwin-arm64@0.27.3 +│ ├── @esbuild/darwin-x64@0.27.3 +│ ├── @esbuild/freebsd-arm64@0.27.3 +│ ├── @esbuild/freebsd-x64@0.27.3 +│ ├── @esbuild/linux-arm@0.27.3 +│ ├── @esbuild/linux-arm64@0.27.3 +│ ├── @esbuild/linux-ia32@0.27.3 +│ ├── @esbuild/linux-loong64@0.27.3 +│ ├── @esbuild/linux-mips64el@0.27.3 +│ ├── @esbuild/linux-ppc64@0.27.3 +│ ├── @esbuild/linux-riscv64@0.27.3 +│ ├── @esbuild/linux-s390x@0.27.3 +│ ├── @esbuild/linux-x64@0.27.3 +│ ├── @esbuild/netbsd-x64@0.27.3 +│ ├── @esbuild/openbsd-x64@0.27.3 +│ ├── @esbuild/sunos-x64@0.27.3 +│ ├── @esbuild/win32-arm64@0.27.3 +│ ├── @esbuild/win32-ia32@0.27.3 +│ └── @esbuild/win32-x64@0.27.3 +├── which@2.0.2 +├── which-boxed-primitive@1.1.1 +├── which-builtin-type@1.2.1 +├── which-collection@1.0.2 +├── which-typed-array@1.1.20 +├── why-is-node-running@2.3.0 +├── word-wrap@1.2.5 +├── wrap-ansi@8.1.0 +│ ├── ansi-styles@6.2.3 +│ └── strip-ansi@7.1.2 +│ └── ansi-regex@6.2.2 +├── wrap-ansi-cjs@7.0.0 +│ └── string-width@4.2.3 +│ └── emoji-regex@8.0.0 +├── wrappy@1.0.2 +├── ws@8.18.3 +├── yallist@3.1.1 +├── yocto-queue@0.1.0 +└── zod@4.3.6 +``` + +## Rust Dependency Tree (cargo tree for safelens-desktop) + +```text +safelens-desktop v0.4.0 (/workspaces/mission-b3dce69f/repo/apps/desktop/src-tauri) +├── alloy v1.7.3 +│ ├── alloy-consensus v1.7.3 +│ │ ├── alloy-eips v1.7.3 +│ │ │ ├── alloy-eip2124 v0.2.0 +│ │ │ │ ├── alloy-primitives v1.5.7 +│ │ │ │ │ ├── alloy-rlp v0.3.13 +│ │ │ │ │ │ ├── alloy-rlp-derive v0.3.13 (proc-macro) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 +│ │ │ │ │ │ │ │ └── unicode-ident v1.0.24 +│ │ │ │ │ │ │ ├── quote v1.0.44 +│ │ │ │ │ │ │ │ └── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── unicode-ident v1.0.24 +│ │ │ │ │ │ ├── arrayvec v0.7.6 +│ │ │ │ │ │ │ └── serde v1.0.228 +│ │ │ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ │ │ └── serde_derive v1.0.228 (proc-macro) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ └── bytes v1.11.1 +│ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ ├── bytes v1.11.1 (*) +│ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ ├── const-hex v1.17.0 +│ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ ├── cpufeatures v0.2.17 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── derive_more v2.1.1 +│ │ │ │ │ │ └── derive_more-impl v2.1.1 (proc-macro) +│ │ │ │ │ │ ├── convert_case v0.10.0 +│ │ │ │ │ │ │ └── unicode-segmentation v1.12.0 +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ ├── syn v2.0.117 (*) +│ │ │ │ │ │ └── unicode-xid v0.2.6 +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── rustc_version v0.4.1 +│ │ │ │ │ │ └── semver v1.0.27 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── foldhash v0.2.0 +│ │ │ │ │ ├── hashbrown v0.16.1 +│ │ │ │ │ │ ├── foldhash v0.2.0 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── indexmap v2.13.0 +│ │ │ │ │ │ ├── equivalent v1.0.2 +│ │ │ │ │ │ ├── hashbrown v0.16.1 (*) +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── itoa v1.0.17 +│ │ │ │ │ ├── k256 v0.13.4 +│ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ ├── ecdsa v0.16.9 +│ │ │ │ │ │ │ ├── der v0.7.10 +│ │ │ │ │ │ │ │ ├── const-oid v0.9.6 +│ │ │ │ │ │ │ │ └── zeroize v1.8.2 +│ │ │ │ │ │ │ │ └── zeroize_derive v1.4.3 (proc-macro) +│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ ├── digest v0.10.7 +│ │ │ │ │ │ │ │ ├── block-buffer v0.10.4 +│ │ │ │ │ │ │ │ │ └── generic-array v0.14.9 +│ │ │ │ │ │ │ │ │ ├── typenum v1.19.0 +│ │ │ │ │ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ │ │ │ └── version_check v0.9.5 +│ │ │ │ │ │ │ │ ├── const-oid v0.9.6 +│ │ │ │ │ │ │ │ ├── crypto-common v0.1.6 +│ │ │ │ │ │ │ │ │ ├── generic-array v0.14.9 (*) +│ │ │ │ │ │ │ │ │ └── typenum v1.19.0 +│ │ │ │ │ │ │ │ └── subtle v2.6.1 +│ │ │ │ │ │ │ ├── elliptic-curve v0.13.8 +│ │ │ │ │ │ │ │ ├── base16ct v0.2.0 +│ │ │ │ │ │ │ │ ├── crypto-bigint v0.5.5 +│ │ │ │ │ │ │ │ │ ├── generic-array v0.14.9 (*) +│ │ │ │ │ │ │ │ │ ├── rand_core v0.6.4 +│ │ │ │ │ │ │ │ │ │ └── getrandom v0.2.17 +│ │ │ │ │ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ │ │ │ │ ├── subtle v2.6.1 +│ │ │ │ │ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ │ │ │ │ ├── digest v0.10.7 (*) +│ │ │ │ │ │ │ │ ├── ff v0.13.1 +│ │ │ │ │ │ │ │ │ ├── bitvec v1.0.1 +│ │ │ │ │ │ │ │ │ │ ├── funty v2.0.0 +│ │ │ │ │ │ │ │ │ │ ├── radium v0.7.0 +│ │ │ │ │ │ │ │ │ │ ├── tap v1.0.1 +│ │ │ │ │ │ │ │ │ │ └── wyz v0.5.1 +│ │ │ │ │ │ │ │ │ │ └── tap v1.0.1 +│ │ │ │ │ │ │ │ │ ├── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ │ └── subtle v2.6.1 +│ │ │ │ │ │ │ │ ├── generic-array v0.14.9 (*) +│ │ │ │ │ │ │ │ ├── group v0.13.0 +│ │ │ │ │ │ │ │ │ ├── ff v0.13.1 (*) +│ │ │ │ │ │ │ │ │ ├── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ │ └── subtle v2.6.1 +│ │ │ │ │ │ │ │ ├── pkcs8 v0.10.2 +│ │ │ │ │ │ │ │ │ ├── der v0.7.10 (*) +│ │ │ │ │ │ │ │ │ └── spki v0.7.3 +│ │ │ │ │ │ │ │ │ └── der v0.7.10 (*) +│ │ │ │ │ │ │ │ ├── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ ├── sec1 v0.7.3 +│ │ │ │ │ │ │ │ │ ├── base16ct v0.2.0 +│ │ │ │ │ │ │ │ │ ├── der v0.7.10 (*) +│ │ │ │ │ │ │ │ │ ├── generic-array v0.14.9 (*) +│ │ │ │ │ │ │ │ │ ├── serdect v0.2.0 +│ │ │ │ │ │ │ │ │ │ ├── base16ct v0.2.0 +│ │ │ │ │ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ │ │ │ │ ├── subtle v2.6.1 +│ │ │ │ │ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ │ │ │ │ ├── serdect v0.2.0 (*) +│ │ │ │ │ │ │ │ ├── subtle v2.6.1 +│ │ │ │ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ │ │ │ ├── rfc6979 v0.4.0 +│ │ │ │ │ │ │ │ ├── hmac v0.12.1 +│ │ │ │ │ │ │ │ │ └── digest v0.10.7 (*) +│ │ │ │ │ │ │ │ └── subtle v2.6.1 +│ │ │ │ │ │ │ ├── serdect v0.2.0 (*) +│ │ │ │ │ │ │ ├── signature v2.2.0 +│ │ │ │ │ │ │ │ ├── digest v0.10.7 (*) +│ │ │ │ │ │ │ │ └── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ └── spki v0.7.3 (*) +│ │ │ │ │ │ ├── elliptic-curve v0.13.8 (*) +│ │ │ │ │ │ ├── serdect v0.2.0 (*) +│ │ │ │ │ │ └── sha2 v0.10.9 +│ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ ├── cpufeatures v0.2.17 +│ │ │ │ │ │ └── digest v0.10.7 (*) +│ │ │ │ │ ├── paste v1.0.15 (proc-macro) +│ │ │ │ │ ├── ruint v1.17.2 +│ │ │ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ │ │ ├── ruint-macro v1.2.1 (proc-macro) +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── rustc-hash v2.1.1 +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ └── sha3 v0.10.8 +│ │ │ │ │ ├── digest v0.10.7 (*) +│ │ │ │ │ └── keccak v0.1.6 +│ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ ├── crc v3.4.0 +│ │ │ │ │ └── crc-catalog v2.4.0 +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ └── thiserror v2.0.18 +│ │ │ │ └── thiserror-impl v2.0.18 (proc-macro) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ ├── alloy-eip2930 v0.2.3 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ └── serde v1.0.228 (*) +│ │ │ ├── alloy-eip7702 v0.6.3 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ ├── k256 v0.13.4 (*) +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ └── thiserror v2.0.18 (*) +│ │ │ ├── alloy-eip7928 v0.3.2 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ └── serde v1.0.228 (*) +│ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ ├── alloy-serde v1.7.3 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ └── serde_json v1.0.149 +│ │ │ │ ├── itoa v1.0.17 +│ │ │ │ ├── memchr v2.8.0 +│ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ └── zmij v1.0.21 +│ │ │ ├── auto_impl v1.3.0 (proc-macro) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ ├── derive_more v2.1.1 (*) +│ │ │ ├── either v1.15.0 +│ │ │ │ └── serde v1.0.228 (*) +│ │ │ ├── ethereum_ssz v0.9.1 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── ethereum_serde_utils v0.8.0 +│ │ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ │ ├── hex v0.4.3 +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ ├── serde_derive v1.0.228 (proc-macro) (*) +│ │ │ │ │ └── serde_json v1.0.149 (*) +│ │ │ │ ├── itertools v0.13.0 +│ │ │ │ │ └── either v1.15.0 (*) +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ ├── serde_derive v1.0.228 (proc-macro) (*) +│ │ │ │ ├── smallvec v1.15.1 +│ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ └── typenum v1.19.0 +│ │ │ ├── ethereum_ssz_derive v0.9.1 (proc-macro) +│ │ │ │ ├── darling v0.20.11 +│ │ │ │ │ ├── darling_core v0.20.11 +│ │ │ │ │ │ ├── fnv v1.0.7 +│ │ │ │ │ │ ├── ident_case v1.0.1 +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ ├── strsim v0.11.1 +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ └── darling_macro v0.20.11 (proc-macro) +│ │ │ │ │ ├── darling_core v0.20.11 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── serde_with v3.16.1 +│ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ └── serde_with_macros v3.16.1 (proc-macro) +│ │ │ │ ├── darling v0.21.3 +│ │ │ │ │ ├── darling_core v0.21.3 +│ │ │ │ │ │ ├── fnv v1.0.7 +│ │ │ │ │ │ ├── ident_case v1.0.1 +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ ├── serde v1.0.228 +│ │ │ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ │ │ └── serde_derive v1.0.228 (proc-macro) (*) +│ │ │ │ │ │ ├── strsim v0.11.1 +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ └── darling_macro v0.21.3 (proc-macro) +│ │ │ │ │ ├── darling_core v0.21.3 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ ├── sha2 v0.10.9 (*) +│ │ │ └── thiserror v2.0.18 (*) +│ │ ├── alloy-primitives v1.5.7 (*) +│ │ ├── alloy-rlp v0.3.13 (*) +│ │ ├── alloy-serde v1.7.3 (*) +│ │ ├── alloy-trie v0.9.4 +│ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ ├── arrayvec v0.7.6 (*) +│ │ │ ├── derive_more v2.1.1 (*) +│ │ │ ├── nybbles v0.4.8 +│ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ ├── ruint v1.17.2 (*) +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ └── smallvec v1.15.1 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── smallvec v1.15.1 (*) +│ │ │ ├── thiserror v2.0.18 (*) +│ │ │ └── tracing v0.1.44 +│ │ │ ├── pin-project-lite v0.2.16 +│ │ │ ├── tracing-attributes v0.1.31 (proc-macro) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ └── tracing-core v0.1.36 +│ │ │ └── once_cell v1.21.3 +│ │ ├── alloy-tx-macros v1.7.3 (proc-macro) +│ │ │ ├── darling v0.21.3 (*) +│ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ ├── quote v1.0.44 (*) +│ │ │ └── syn v2.0.117 (*) +│ │ ├── auto_impl v1.3.0 (proc-macro) (*) +│ │ ├── derive_more v2.1.1 (*) +│ │ ├── either v1.15.0 (*) +│ │ ├── k256 v0.13.4 (*) +│ │ ├── once_cell v1.21.3 +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_json v1.0.149 (*) +│ │ └── thiserror v2.0.18 (*) +│ ├── alloy-core v1.5.7 +│ │ ├── alloy-primitives v1.5.7 (*) +│ │ └── alloy-rlp v0.3.13 (*) +│ ├── alloy-eips v1.7.3 (*) +│ ├── alloy-rpc-types v1.7.3 +│ │ ├── alloy-primitives v1.5.7 (*) +│ │ ├── alloy-rpc-types-eth v1.7.3 +│ │ │ ├── alloy-consensus v1.7.3 (*) +│ │ │ ├── alloy-consensus-any v1.7.3 +│ │ │ │ ├── alloy-consensus v1.7.3 (*) +│ │ │ │ ├── alloy-eips v1.7.3 (*) +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ ├── alloy-serde v1.7.3 (*) +│ │ │ │ └── serde v1.0.228 (*) +│ │ │ ├── alloy-eips v1.7.3 (*) +│ │ │ ├── alloy-network-primitives v1.7.3 +│ │ │ │ ├── alloy-consensus v1.7.3 (*) +│ │ │ │ ├── alloy-eips v1.7.3 (*) +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── alloy-serde v1.7.3 (*) +│ │ │ │ └── serde v1.0.228 (*) +│ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ ├── alloy-serde v1.7.3 (*) +│ │ │ ├── alloy-sol-types v1.5.7 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ └── alloy-sol-macro v1.5.7 (proc-macro) +│ │ │ │ ├── alloy-sol-macro-expander v1.5.7 +│ │ │ │ │ ├── alloy-sol-macro-input v1.5.7 +│ │ │ │ │ │ ├── const-hex v1.17.0 +│ │ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ │ └── cpufeatures v0.2.17 +│ │ │ │ │ │ ├── dunce v1.0.5 +│ │ │ │ │ │ ├── heck v0.5.0 +│ │ │ │ │ │ ├── macro-string v0.1.4 +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ ├── syn v2.0.117 (*) +│ │ │ │ │ │ └── syn-solidity v1.5.7 +│ │ │ │ │ │ ├── paste v1.0.15 (proc-macro) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ ├── const-hex v1.17.0 (*) +│ │ │ │ │ ├── heck v0.5.0 +│ │ │ │ │ ├── indexmap v2.13.0 +│ │ │ │ │ │ ├── equivalent v1.0.2 +│ │ │ │ │ │ └── hashbrown v0.16.1 +│ │ │ │ │ ├── proc-macro-error2 v2.0.1 +│ │ │ │ │ │ ├── proc-macro-error-attr2 v2.0.0 (proc-macro) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ └── quote v1.0.44 (*) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ ├── sha3 v0.10.8 +│ │ │ │ │ │ ├── digest v0.10.7 +│ │ │ │ │ │ │ ├── block-buffer v0.10.4 (*) +│ │ │ │ │ │ │ └── crypto-common v0.1.6 (*) +│ │ │ │ │ │ └── keccak v0.1.6 +│ │ │ │ │ ├── syn v2.0.117 (*) +│ │ │ │ │ └── syn-solidity v1.5.7 (*) +│ │ │ │ ├── alloy-sol-macro-input v1.5.7 (*) +│ │ │ │ ├── proc-macro-error2 v2.0.1 (*) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ ├── itertools v0.14.0 +│ │ │ │ └── either v1.15.0 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── serde_json v1.0.149 (*) +│ │ │ └── thiserror v2.0.18 (*) +│ │ ├── alloy-serde v1.7.3 (*) +│ │ └── serde v1.0.228 (*) +│ └── alloy-serde v1.7.3 (*) +├── eyre v0.6.12 +│ ├── indenter v0.3.4 +│ └── once_cell v1.21.3 +├── helios-consensus-core v0.11.0 (https://github.com/a16z/helios?rev=582fda319ed1ecb5fb82c71f4fa755a32e01031a#582fda31) +│ ├── alloy v1.7.3 (*) +│ ├── alloy-rlp v0.3.13 (*) +│ ├── bls12_381 v0.8.0 +│ │ ├── digest v0.9.0 +│ │ │ └── generic-array v0.14.9 (*) +│ │ ├── ff v0.13.1 (*) +│ │ ├── group v0.13.0 (*) +│ │ ├── pairing v0.23.0 +│ │ │ └── group v0.13.0 (*) +│ │ ├── rand_core v0.6.4 (*) +│ │ └── subtle v2.6.1 +│ ├── ethereum_ssz v0.9.1 (*) +│ ├── ethereum_ssz_derive v0.9.1 (proc-macro) (*) +│ ├── eyre v0.6.12 (*) +│ ├── serde v1.0.228 (*) +│ ├── sha2 v0.9.9 +│ │ ├── block-buffer v0.9.0 +│ │ │ └── generic-array v0.14.9 (*) +│ │ ├── cfg-if v1.0.4 +│ │ ├── cpufeatures v0.2.17 +│ │ ├── digest v0.9.0 (*) +│ │ └── opaque-debug v0.3.1 +│ ├── ssz_types v0.11.0 +│ │ ├── ethereum_serde_utils v0.8.0 (*) +│ │ ├── ethereum_ssz v0.9.1 (*) +│ │ ├── itertools v0.13.0 (*) +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_derive v1.0.228 (proc-macro) (*) +│ │ ├── smallvec v1.15.1 (*) +│ │ ├── tree_hash v0.10.0 +│ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ ├── ethereum_hashing v0.7.0 (https://github.com/ncitron/ethereum_hashing?rev=7ee70944ed4fabe301551da8c447e4f4ae5e6c35#7ee70944) +│ │ │ │ ├── cpufeatures v0.2.17 +│ │ │ │ └── sha2 v0.10.9 (*) +│ │ │ ├── ethereum_ssz v0.9.1 (*) +│ │ │ ├── smallvec v1.15.1 (*) +│ │ │ └── typenum v1.19.0 +│ │ └── typenum v1.19.0 +│ ├── superstruct v0.7.0 (proc-macro) +│ │ ├── darling v0.13.4 +│ │ │ ├── darling_core v0.13.4 +│ │ │ │ ├── fnv v1.0.7 +│ │ │ │ ├── ident_case v1.0.1 +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ ├── strsim v0.10.0 +│ │ │ │ └── syn v1.0.109 +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── unicode-ident v1.0.24 +│ │ │ └── darling_macro v0.13.4 (proc-macro) +│ │ │ ├── darling_core v0.13.4 (*) +│ │ │ ├── quote v1.0.44 (*) +│ │ │ └── syn v1.0.109 (*) +│ │ ├── itertools v0.10.5 +│ │ │ └── either v1.15.0 +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ ├── smallvec v1.15.1 +│ │ └── syn v1.0.109 (*) +│ ├── thiserror v1.0.69 +│ │ └── thiserror-impl v1.0.69 (proc-macro) +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ └── syn v2.0.117 (*) +│ ├── tracing v0.1.44 (*) +│ ├── tree_hash v0.10.0 (*) +│ ├── tree_hash_derive v0.10.0 (proc-macro) +│ │ ├── darling v0.20.11 (*) +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ └── syn v2.0.117 (*) +│ └── typenum v1.19.0 +├── hex v0.4.3 +├── revm v34.0.0 +│ ├── revm-bytecode v8.0.0 +│ │ ├── bitvec v1.0.1 (*) +│ │ └── revm-primitives v22.0.0 +│ │ ├── alloy-primitives v1.5.7 (*) +│ │ ├── num_enum v0.7.5 +│ │ │ ├── num_enum_derive v0.7.5 (proc-macro) +│ │ │ │ ├── proc-macro-crate v3.4.0 +│ │ │ │ │ └── toml_edit v0.23.10+spec-1.0.0 +│ │ │ │ │ ├── indexmap v2.13.0 (*) +│ │ │ │ │ ├── toml_datetime v0.7.5+spec-1.1.0 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── toml_parser v1.0.9+spec-1.1.0 +│ │ │ │ │ │ └── winnow v0.7.14 +│ │ │ │ │ └── winnow v0.7.14 +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ └── rustversion v1.0.22 (proc-macro) +│ │ └── once_cell v1.21.3 +│ ├── revm-context v13.0.0 +│ │ ├── bitvec v1.0.1 (*) +│ │ ├── cfg-if v1.0.4 +│ │ ├── derive-where v1.6.0 (proc-macro) +│ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ ├── quote v1.0.44 (*) +│ │ │ └── syn v2.0.117 (*) +│ │ ├── revm-bytecode v8.0.0 (*) +│ │ ├── revm-context-interface v14.0.0 +│ │ │ ├── alloy-eip2930 v0.2.3 (*) +│ │ │ ├── alloy-eip7702 v0.6.3 (*) +│ │ │ ├── auto_impl v1.3.0 (proc-macro) (*) +│ │ │ ├── either v1.15.0 (*) +│ │ │ ├── revm-database-interface v9.0.0 +│ │ │ │ ├── auto_impl v1.3.0 (proc-macro) (*) +│ │ │ │ ├── either v1.15.0 (*) +│ │ │ │ ├── revm-primitives v22.0.0 (*) +│ │ │ │ ├── revm-state v9.0.0 +│ │ │ │ │ ├── alloy-eip7928 v0.3.2 (*) +│ │ │ │ │ ├── bitflags v2.11.0 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── revm-bytecode v8.0.0 (*) +│ │ │ │ │ └── revm-primitives v22.0.0 (*) +│ │ │ │ └── thiserror v2.0.18 (*) +│ │ │ ├── revm-primitives v22.0.0 (*) +│ │ │ └── revm-state v9.0.0 (*) +│ │ ├── revm-database-interface v9.0.0 (*) +│ │ ├── revm-primitives v22.0.0 (*) +│ │ └── revm-state v9.0.0 (*) +│ ├── revm-context-interface v14.0.0 (*) +│ ├── revm-database v10.0.0 +│ │ ├── revm-bytecode v8.0.0 (*) +│ │ ├── revm-database-interface v9.0.0 (*) +│ │ ├── revm-primitives v22.0.0 (*) +│ │ └── revm-state v9.0.0 (*) +│ ├── revm-database-interface v9.0.0 (*) +│ ├── revm-handler v15.0.0 +│ │ ├── auto_impl v1.3.0 (proc-macro) (*) +│ │ ├── derive-where v1.6.0 (proc-macro) (*) +│ │ ├── revm-bytecode v8.0.0 (*) +│ │ ├── revm-context v13.0.0 (*) +│ │ ├── revm-context-interface v14.0.0 (*) +│ │ ├── revm-database-interface v9.0.0 (*) +│ │ ├── revm-interpreter v32.0.0 +│ │ │ ├── revm-bytecode v8.0.0 (*) +│ │ │ ├── revm-context-interface v14.0.0 (*) +│ │ │ ├── revm-primitives v22.0.0 (*) +│ │ │ └── revm-state v9.0.0 (*) +│ │ ├── revm-precompile v32.0.0 +│ │ │ ├── ark-bls12-381 v0.5.0 +│ │ │ │ ├── ark-ec v0.5.0 +│ │ │ │ │ ├── ahash v0.8.12 +│ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ ├── once_cell v1.21.3 +│ │ │ │ │ │ └── zerocopy v0.8.39 +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── version_check v0.9.5 +│ │ │ │ │ ├── ark-ff v0.5.0 +│ │ │ │ │ │ ├── ark-ff-asm v0.5.0 (proc-macro) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ ├── ark-ff-macros v0.5.0 (proc-macro) +│ │ │ │ │ │ │ ├── num-bigint v0.4.6 +│ │ │ │ │ │ │ │ ├── num-integer v0.1.46 +│ │ │ │ │ │ │ │ │ └── num-traits v0.2.19 +│ │ │ │ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ │ │ │ └── autocfg v1.5.0 +│ │ │ │ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ │ │ │ ├── num-traits v0.2.19 (*) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ ├── ark-serialize v0.5.0 +│ │ │ │ │ │ │ ├── ark-serialize-derive v0.5.0 (proc-macro) +│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ ├── ark-std v0.5.0 +│ │ │ │ │ │ │ │ ├── num-traits v0.2.19 +│ │ │ │ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ │ │ │ └── autocfg v1.5.0 +│ │ │ │ │ │ │ │ └── rand v0.8.5 +│ │ │ │ │ │ │ │ ├── rand_chacha v0.3.1 +│ │ │ │ │ │ │ │ │ ├── ppv-lite86 v0.2.21 +│ │ │ │ │ │ │ │ │ │ └── zerocopy v0.8.39 +│ │ │ │ │ │ │ │ │ └── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ └── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ ├── arrayvec v0.7.6 (*) +│ │ │ │ │ │ │ ├── digest v0.10.7 (*) +│ │ │ │ │ │ │ └── num-bigint v0.4.6 +│ │ │ │ │ │ │ ├── num-integer v0.1.46 +│ │ │ │ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ │ │ ├── ark-std v0.5.0 (*) +│ │ │ │ │ │ ├── arrayvec v0.7.6 (*) +│ │ │ │ │ │ ├── digest v0.10.7 (*) +│ │ │ │ │ │ ├── educe v0.6.0 (proc-macro) +│ │ │ │ │ │ │ ├── enum-ordinalize v4.3.2 +│ │ │ │ │ │ │ │ └── enum-ordinalize-derive v4.3.2 (proc-macro) +│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ ├── itertools v0.13.0 (*) +│ │ │ │ │ │ ├── num-bigint v0.4.6 (*) +│ │ │ │ │ │ ├── num-traits v0.2.19 (*) +│ │ │ │ │ │ ├── paste v1.0.15 (proc-macro) +│ │ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ │ ├── ark-poly v0.5.0 +│ │ │ │ │ │ ├── ahash v0.8.12 (*) +│ │ │ │ │ │ ├── ark-ff v0.5.0 (*) +│ │ │ │ │ │ ├── ark-serialize v0.5.0 (*) +│ │ │ │ │ │ ├── ark-std v0.5.0 (*) +│ │ │ │ │ │ ├── educe v0.6.0 (proc-macro) (*) +│ │ │ │ │ │ └── hashbrown v0.15.5 +│ │ │ │ │ │ └── allocator-api2 v0.2.21 +│ │ │ │ │ ├── ark-serialize v0.5.0 (*) +│ │ │ │ │ ├── ark-std v0.5.0 (*) +│ │ │ │ │ ├── educe v0.6.0 (proc-macro) (*) +│ │ │ │ │ ├── hashbrown v0.15.5 (*) +│ │ │ │ │ ├── itertools v0.13.0 (*) +│ │ │ │ │ ├── num-bigint v0.4.6 (*) +│ │ │ │ │ ├── num-integer v0.1.46 (*) +│ │ │ │ │ ├── num-traits v0.2.19 (*) +│ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ ├── ark-ff v0.5.0 (*) +│ │ │ │ ├── ark-serialize v0.5.0 (*) +│ │ │ │ └── ark-std v0.5.0 (*) +│ │ │ ├── ark-bn254 v0.5.0 +│ │ │ │ ├── ark-ec v0.5.0 (*) +│ │ │ │ ├── ark-ff v0.5.0 (*) +│ │ │ │ └── ark-std v0.5.0 (*) +│ │ │ ├── ark-ec v0.5.0 (*) +│ │ │ ├── ark-ff v0.5.0 (*) +│ │ │ ├── ark-serialize v0.5.0 (*) +│ │ │ ├── arrayref v0.3.9 +│ │ │ ├── aurora-engine-modexp v1.2.0 +│ │ │ │ ├── hex v0.4.3 +│ │ │ │ └── num v0.4.3 +│ │ │ │ ├── num-bigint v0.4.6 (*) +│ │ │ │ ├── num-complex v0.4.6 +│ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ ├── num-integer v0.1.46 (*) +│ │ │ │ ├── num-iter v0.1.45 +│ │ │ │ │ ├── num-integer v0.1.46 (*) +│ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── autocfg v1.5.0 +│ │ │ │ ├── num-rational v0.4.2 +│ │ │ │ │ ├── num-bigint v0.4.6 (*) +│ │ │ │ │ ├── num-integer v0.1.46 (*) +│ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ ├── cfg-if v1.0.4 +│ │ │ ├── k256 v0.13.4 (*) +│ │ │ ├── p256 v0.13.2 +│ │ │ │ ├── ecdsa v0.16.9 (*) +│ │ │ │ ├── elliptic-curve v0.13.8 (*) +│ │ │ │ ├── primeorder v0.13.6 +│ │ │ │ │ └── elliptic-curve v0.13.8 (*) +│ │ │ │ └── sha2 v0.10.9 (*) +│ │ │ ├── revm-primitives v22.0.0 (*) +│ │ │ ├── ripemd v0.1.3 +│ │ │ │ └── digest v0.10.7 (*) +│ │ │ └── sha2 v0.10.9 (*) +│ │ ├── revm-primitives v22.0.0 (*) +│ │ └── revm-state v9.0.0 (*) +│ ├── revm-inspector v15.0.0 +│ │ ├── auto_impl v1.3.0 (proc-macro) (*) +│ │ ├── either v1.15.0 (*) +│ │ ├── revm-context v13.0.0 (*) +│ │ ├── revm-database-interface v9.0.0 (*) +│ │ ├── revm-handler v15.0.0 (*) +│ │ ├── revm-interpreter v32.0.0 (*) +│ │ ├── revm-primitives v22.0.0 (*) +│ │ └── revm-state v9.0.0 (*) +│ ├── revm-interpreter v32.0.0 (*) +│ ├── revm-precompile v32.0.0 (*) +│ ├── revm-primitives v22.0.0 (*) +│ └── revm-state v9.0.0 (*) +├── serde v1.0.228 (*) +├── serde_json v1.0.149 (*) +├── tauri v2.10.2 +│ ├── anyhow v1.0.102 +│ ├── cookie v0.18.1 +│ │ └── time v0.3.47 +│ │ ├── deranged v0.5.8 +│ │ │ └── powerfmt v0.2.0 +│ │ ├── itoa v1.0.17 +│ │ ├── num-conv v0.2.0 +│ │ ├── powerfmt v0.2.0 +│ │ ├── time-core v0.1.8 +│ │ └── time-macros v0.2.27 (proc-macro) +│ │ ├── num-conv v0.2.0 +│ │ └── time-core v0.1.8 +│ │ [build-dependencies] +│ │ └── version_check v0.9.5 +│ ├── dirs v6.0.0 +│ │ └── dirs-sys v0.5.0 +│ │ ├── libc v0.2.182 +│ │ └── option-ext v0.2.0 +│ ├── dunce v1.0.5 +│ ├── getrandom v0.3.4 +│ │ ├── cfg-if v1.0.4 +│ │ └── libc v0.2.182 +│ ├── glob v0.3.3 +│ ├── gtk v0.18.2 +│ │ ├── atk v0.18.2 +│ │ │ ├── atk-sys v0.18.2 +│ │ │ │ ├── glib-sys v0.18.1 +│ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── system-deps v6.2.2 +│ │ │ │ │ ├── cfg-expr v0.15.8 +│ │ │ │ │ │ ├── smallvec v1.15.1 +│ │ │ │ │ │ └── target-lexicon v0.12.16 +│ │ │ │ │ ├── heck v0.5.0 +│ │ │ │ │ ├── pkg-config v0.3.32 +│ │ │ │ │ ├── toml v0.8.2 +│ │ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ │ ├── serde_spanned v0.6.9 +│ │ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ │ ├── toml_datetime v0.6.3 +│ │ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ │ └── toml_edit v0.20.2 +│ │ │ │ │ │ ├── indexmap v2.13.0 (*) +│ │ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ │ ├── serde_spanned v0.6.9 (*) +│ │ │ │ │ │ ├── toml_datetime v0.6.3 (*) +│ │ │ │ │ │ └── winnow v0.5.40 +│ │ │ │ │ └── version-compare v0.2.1 +│ │ │ │ ├── gobject-sys v0.18.0 +│ │ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ │ └── libc v0.2.182 +│ │ │ │ [build-dependencies] +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ ├── glib v0.18.5 +│ │ │ │ ├── bitflags v2.11.0 (*) +│ │ │ │ ├── futures-channel v0.3.32 +│ │ │ │ │ └── futures-core v0.3.32 +│ │ │ │ ├── futures-core v0.3.32 +│ │ │ │ ├── futures-executor v0.3.32 +│ │ │ │ │ ├── futures-core v0.3.32 +│ │ │ │ │ ├── futures-task v0.3.32 +│ │ │ │ │ └── futures-util v0.3.32 +│ │ │ │ │ ├── futures-core v0.3.32 +│ │ │ │ │ ├── futures-macro v0.3.32 (proc-macro) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ ├── futures-task v0.3.32 +│ │ │ │ │ ├── pin-project-lite v0.2.16 +│ │ │ │ │ └── slab v0.4.12 +│ │ │ │ ├── futures-task v0.3.32 +│ │ │ │ ├── futures-util v0.3.32 (*) +│ │ │ │ ├── gio-sys v0.18.1 +│ │ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ │ ├── glib-macros v0.18.5 (proc-macro) +│ │ │ │ │ ├── heck v0.4.1 +│ │ │ │ │ ├── proc-macro-crate v2.0.2 +│ │ │ │ │ │ ├── toml_datetime v0.6.3 (*) +│ │ │ │ │ │ └── toml_edit v0.20.2 (*) +│ │ │ │ │ ├── proc-macro-error v1.0.4 +│ │ │ │ │ │ ├── proc-macro-error-attr v1.0.4 (proc-macro) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ └── quote v1.0.44 (*) +│ │ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ │ └── version_check v0.9.5 +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v1.0.109 (*) +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── version_check v0.9.5 +│ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ ├── libc v0.2.182 +│ │ │ │ ├── memchr v2.8.0 +│ │ │ │ ├── once_cell v1.21.3 +│ │ │ │ ├── smallvec v1.15.1 (*) +│ │ │ │ └── thiserror v1.0.69 (*) +│ │ │ └── libc v0.2.182 +│ │ ├── cairo-rs v0.18.5 +│ │ │ ├── bitflags v2.11.0 (*) +│ │ │ ├── cairo-sys-rs v0.18.2 +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ └── libc v0.2.182 +│ │ │ │ [build-dependencies] +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ ├── glib v0.18.5 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ ├── once_cell v1.21.3 +│ │ │ └── thiserror v1.0.69 (*) +│ │ ├── field-offset v0.3.6 +│ │ │ └── memoffset v0.9.1 +│ │ │ [build-dependencies] +│ │ │ └── autocfg v1.5.0 +│ │ │ [build-dependencies] +│ │ │ └── rustc_version v0.4.1 (*) +│ │ ├── futures-channel v0.3.32 (*) +│ │ ├── gdk v0.18.2 +│ │ │ ├── cairo-rs v0.18.5 (*) +│ │ │ ├── gdk-pixbuf v0.18.5 +│ │ │ │ ├── gdk-pixbuf-sys v0.18.0 +│ │ │ │ │ ├── gio-sys v0.18.1 (*) +│ │ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ │ ├── gio v0.18.4 +│ │ │ │ │ ├── futures-channel v0.3.32 (*) +│ │ │ │ │ ├── futures-core v0.3.32 +│ │ │ │ │ ├── futures-io v0.3.32 +│ │ │ │ │ ├── futures-util v0.3.32 (*) +│ │ │ │ │ ├── gio-sys v0.18.1 (*) +│ │ │ │ │ ├── glib v0.18.5 (*) +│ │ │ │ │ ├── libc v0.2.182 +│ │ │ │ │ ├── once_cell v1.21.3 +│ │ │ │ │ ├── pin-project-lite v0.2.16 +│ │ │ │ │ ├── smallvec v1.15.1 (*) +│ │ │ │ │ └── thiserror v1.0.69 (*) +│ │ │ │ ├── glib v0.18.5 (*) +│ │ │ │ ├── libc v0.2.182 +│ │ │ │ └── once_cell v1.21.3 +│ │ │ ├── gdk-sys v0.18.2 +│ │ │ │ ├── cairo-sys-rs v0.18.2 (*) +│ │ │ │ ├── gdk-pixbuf-sys v0.18.0 (*) +│ │ │ │ ├── gio-sys v0.18.1 (*) +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ ├── libc v0.2.182 +│ │ │ │ └── pango-sys v0.18.0 +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ └── libc v0.2.182 +│ │ │ │ [build-dependencies] +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ │ [build-dependencies] +│ │ │ │ ├── pkg-config v0.3.32 +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ ├── gio v0.18.4 (*) +│ │ │ ├── glib v0.18.5 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ └── pango v0.18.3 +│ │ │ ├── gio v0.18.4 (*) +│ │ │ ├── glib v0.18.5 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ ├── once_cell v1.21.3 +│ │ │ └── pango-sys v0.18.0 (*) +│ │ ├── gdk-pixbuf v0.18.5 (*) +│ │ ├── gio v0.18.4 (*) +│ │ ├── glib v0.18.5 (*) +│ │ ├── gtk-sys v0.18.2 +│ │ │ ├── atk-sys v0.18.2 (*) +│ │ │ ├── cairo-sys-rs v0.18.2 (*) +│ │ │ ├── gdk-pixbuf-sys v0.18.0 (*) +│ │ │ ├── gdk-sys v0.18.2 (*) +│ │ │ ├── gio-sys v0.18.1 (*) +│ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ └── pango-sys v0.18.0 (*) +│ │ │ [build-dependencies] +│ │ │ └── system-deps v6.2.2 (*) +│ │ ├── gtk3-macros v0.18.2 (proc-macro) +│ │ │ ├── proc-macro-crate v1.3.1 +│ │ │ │ ├── once_cell v1.21.3 +│ │ │ │ └── toml_edit v0.19.15 +│ │ │ │ ├── indexmap v2.13.0 (*) +│ │ │ │ ├── toml_datetime v0.6.3 (*) +│ │ │ │ └── winnow v0.5.40 +│ │ │ ├── proc-macro-error v1.0.4 (*) +│ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ ├── quote v1.0.44 (*) +│ │ │ └── syn v2.0.117 (*) +│ │ ├── libc v0.2.182 +│ │ └── pango v0.18.3 (*) +│ │ [build-dependencies] +│ │ └── pkg-config v0.3.32 +│ ├── heck v0.5.0 +│ ├── http v1.4.0 +│ │ ├── bytes v1.11.1 (*) +│ │ └── itoa v1.0.17 +│ ├── log v0.4.29 +│ ├── mime v0.3.17 +│ ├── muda v0.17.1 +│ │ ├── crossbeam-channel v0.5.15 +│ │ │ └── crossbeam-utils v0.8.21 +│ │ ├── dpi v0.1.2 +│ │ │ └── serde v1.0.228 (*) +│ │ ├── gtk v0.18.2 (*) +│ │ ├── keyboard-types v0.7.0 +│ │ │ ├── bitflags v2.11.0 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ └── unicode-segmentation v1.12.0 +│ │ ├── once_cell v1.21.3 +│ │ ├── serde v1.0.228 (*) +│ │ └── thiserror v2.0.18 (*) +│ ├── percent-encoding v2.3.2 +│ ├── raw-window-handle v0.6.2 +│ ├── serde v1.0.228 (*) +│ ├── serde_json v1.0.149 (*) +│ ├── serde_repr v0.1.20 (proc-macro) +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ └── syn v2.0.117 (*) +│ ├── serialize-to-javascript v0.1.2 +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_json v1.0.149 (*) +│ │ └── serialize-to-javascript-impl v0.1.2 (proc-macro) +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ └── syn v2.0.117 (*) +│ ├── tauri-macros v2.5.4 (proc-macro) +│ │ ├── heck v0.5.0 +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ ├── syn v2.0.117 (*) +│ │ ├── tauri-codegen v2.5.4 +│ │ │ ├── base64 v0.22.1 +│ │ │ ├── brotli v8.0.2 +│ │ │ │ ├── alloc-no-stdlib v2.0.4 +│ │ │ │ ├── alloc-stdlib v0.2.2 +│ │ │ │ │ └── alloc-no-stdlib v2.0.4 +│ │ │ │ └── brotli-decompressor v5.0.0 +│ │ │ │ ├── alloc-no-stdlib v2.0.4 +│ │ │ │ └── alloc-stdlib v0.2.2 (*) +│ │ │ ├── ico v0.5.0 +│ │ │ │ ├── byteorder v1.5.0 +│ │ │ │ └── png v0.17.16 +│ │ │ │ ├── bitflags v1.3.2 +│ │ │ │ ├── crc32fast v1.5.0 +│ │ │ │ │ └── cfg-if v1.0.4 +│ │ │ │ ├── fdeflate v0.3.7 +│ │ │ │ │ └── simd-adler32 v0.3.8 +│ │ │ │ ├── flate2 v1.1.9 +│ │ │ │ │ ├── crc32fast v1.5.0 (*) +│ │ │ │ │ └── miniz_oxide v0.8.9 +│ │ │ │ │ ├── adler2 v2.0.1 +│ │ │ │ │ └── simd-adler32 v0.3.8 +│ │ │ │ └── miniz_oxide v0.8.9 (*) +│ │ │ ├── json-patch v3.0.1 +│ │ │ │ ├── jsonptr v0.6.3 +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ └── serde_json v1.0.149 +│ │ │ │ │ ├── itoa v1.0.17 +│ │ │ │ │ ├── memchr v2.8.0 +│ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ └── zmij v1.0.21 +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ ├── serde_json v1.0.149 (*) +│ │ │ │ └── thiserror v1.0.69 (*) +│ │ │ ├── png v0.17.16 (*) +│ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ ├── quote v1.0.44 (*) +│ │ │ ├── semver v1.0.27 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── serde_json v1.0.149 (*) +│ │ │ ├── sha2 v0.10.9 (*) +│ │ │ ├── syn v2.0.117 (*) +│ │ │ ├── tauri-utils v2.8.2 +│ │ │ │ ├── anyhow v1.0.102 +│ │ │ │ ├── brotli v8.0.2 (*) +│ │ │ │ ├── cargo_metadata v0.19.2 +│ │ │ │ │ ├── camino v1.2.2 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── cargo-platform v0.1.9 +│ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ ├── semver v1.0.27 (*) +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ ├── serde_json v1.0.149 (*) +│ │ │ │ │ └── thiserror v2.0.18 (*) +│ │ │ │ ├── ctor v0.2.9 (proc-macro) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── dunce v1.0.5 +│ │ │ │ ├── glob v0.3.3 +│ │ │ │ ├── html5ever v0.29.1 +│ │ │ │ │ ├── log v0.4.29 +│ │ │ │ │ ├── mac v0.1.1 +│ │ │ │ │ ├── markup5ever v0.14.1 +│ │ │ │ │ │ ├── log v0.4.29 +│ │ │ │ │ │ ├── phf v0.11.3 +│ │ │ │ │ │ │ ├── phf_macros v0.11.3 (proc-macro) +│ │ │ │ │ │ │ │ ├── phf_generator v0.11.3 +│ │ │ │ │ │ │ │ │ ├── phf_shared v0.11.3 +│ │ │ │ │ │ │ │ │ │ └── siphasher v1.0.2 +│ │ │ │ │ │ │ │ │ └── rand v0.8.5 +│ │ │ │ │ │ │ │ │ ├── libc v0.2.182 +│ │ │ │ │ │ │ │ │ ├── rand_chacha v0.3.1 +│ │ │ │ │ │ │ │ │ │ ├── ppv-lite86 v0.2.21 +│ │ │ │ │ │ │ │ │ │ │ └── zerocopy v0.8.39 +│ │ │ │ │ │ │ │ │ │ └── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ │ └── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ ├── phf_shared v0.11.3 (*) +│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ └── phf_shared v0.11.3 (*) +│ │ │ │ │ │ ├── string_cache v0.8.9 +│ │ │ │ │ │ │ ├── new_debug_unreachable v1.0.6 +│ │ │ │ │ │ │ ├── parking_lot v0.12.5 +│ │ │ │ │ │ │ │ ├── lock_api v0.4.14 +│ │ │ │ │ │ │ │ │ └── scopeguard v1.2.0 +│ │ │ │ │ │ │ │ └── parking_lot_core v0.9.12 +│ │ │ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ │ │ ├── libc v0.2.182 +│ │ │ │ │ │ │ │ └── smallvec v1.15.1 +│ │ │ │ │ │ │ ├── phf_shared v0.11.3 (*) +│ │ │ │ │ │ │ ├── precomputed-hash v0.1.1 +│ │ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ │ └── tendril v0.4.3 +│ │ │ │ │ │ ├── futf v0.1.5 +│ │ │ │ │ │ │ ├── mac v0.1.1 +│ │ │ │ │ │ │ └── new_debug_unreachable v1.0.6 +│ │ │ │ │ │ ├── mac v0.1.1 +│ │ │ │ │ │ └── utf-8 v0.7.6 +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ ├── phf_codegen v0.11.3 +│ │ │ │ │ │ │ ├── phf_generator v0.11.3 (*) +│ │ │ │ │ │ │ └── phf_shared v0.11.3 (*) +│ │ │ │ │ │ └── string_cache_codegen v0.5.4 +│ │ │ │ │ │ ├── phf_generator v0.11.3 (*) +│ │ │ │ │ │ ├── phf_shared v0.11.3 (*) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ └── quote v1.0.44 (*) +│ │ │ │ │ └── match_token v0.1.0 (proc-macro) +│ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── http v1.4.0 (*) +│ │ │ │ ├── infer v0.19.0 +│ │ │ │ │ └── cfb v0.7.3 +│ │ │ │ │ ├── byteorder v1.5.0 +│ │ │ │ │ ├── fnv v1.0.7 +│ │ │ │ │ └── uuid v1.21.0 +│ │ │ │ │ ├── getrandom v0.4.1 +│ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ ├── json-patch v3.0.1 (*) +│ │ │ │ ├── kuchikiki v0.8.8-speedreader +│ │ │ │ │ ├── cssparser v0.29.6 +│ │ │ │ │ │ ├── cssparser-macros v0.6.1 (proc-macro) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ ├── dtoa-short v0.3.5 +│ │ │ │ │ │ │ └── dtoa v1.0.11 +│ │ │ │ │ │ ├── itoa v1.0.17 +│ │ │ │ │ │ ├── matches v0.1.10 +│ │ │ │ │ │ ├── phf v0.10.1 +│ │ │ │ │ │ │ ├── phf_macros v0.10.0 (proc-macro) +│ │ │ │ │ │ │ │ ├── phf_generator v0.10.0 +│ │ │ │ │ │ │ │ │ ├── phf_shared v0.10.0 +│ │ │ │ │ │ │ │ │ │ └── siphasher v0.3.11 +│ │ │ │ │ │ │ │ │ └── rand v0.8.5 (*) +│ │ │ │ │ │ │ │ ├── phf_shared v0.10.0 (*) +│ │ │ │ │ │ │ │ ├── proc-macro-hack v0.5.20+deprecated (proc-macro) +│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ └── syn v1.0.109 (*) +│ │ │ │ │ │ │ ├── phf_shared v0.10.0 (*) +│ │ │ │ │ │ │ └── proc-macro-hack v0.5.20+deprecated (proc-macro) +│ │ │ │ │ │ └── smallvec v1.15.1 +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v1.0.109 (*) +│ │ │ │ │ ├── html5ever v0.29.1 (*) +│ │ │ │ │ ├── indexmap v2.13.0 (*) +│ │ │ │ │ └── selectors v0.24.0 +│ │ │ │ │ ├── bitflags v1.3.2 +│ │ │ │ │ ├── cssparser v0.29.6 (*) +│ │ │ │ │ ├── derive_more v0.99.20 (proc-macro) +│ │ │ │ │ │ ├── convert_case v0.4.0 +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── rustc_version v0.4.1 (*) +│ │ │ │ │ ├── fxhash v0.2.1 +│ │ │ │ │ │ └── byteorder v1.5.0 +│ │ │ │ │ ├── log v0.4.29 +│ │ │ │ │ ├── phf v0.8.0 +│ │ │ │ │ │ └── phf_shared v0.8.0 +│ │ │ │ │ │ └── siphasher v0.3.11 +│ │ │ │ │ ├── precomputed-hash v0.1.1 +│ │ │ │ │ ├── servo_arc v0.2.0 +│ │ │ │ │ │ ├── nodrop v0.1.14 +│ │ │ │ │ │ └── stable_deref_trait v1.2.1 +│ │ │ │ │ └── smallvec v1.15.1 +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── phf_codegen v0.8.0 +│ │ │ │ │ ├── phf_generator v0.8.0 +│ │ │ │ │ │ ├── phf_shared v0.8.0 (*) +│ │ │ │ │ │ └── rand v0.7.3 +│ │ │ │ │ │ ├── getrandom v0.1.16 +│ │ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ │ ├── libc v0.2.182 +│ │ │ │ │ │ ├── rand_chacha v0.2.2 +│ │ │ │ │ │ │ ├── ppv-lite86 v0.2.21 (*) +│ │ │ │ │ │ │ └── rand_core v0.5.1 +│ │ │ │ │ │ │ └── getrandom v0.1.16 (*) +│ │ │ │ │ │ ├── rand_core v0.5.1 (*) +│ │ │ │ │ │ └── rand_pcg v0.2.1 +│ │ │ │ │ │ └── rand_core v0.5.1 (*) +│ │ │ │ │ └── phf_shared v0.8.0 (*) +│ │ │ │ ├── log v0.4.29 +│ │ │ │ ├── memchr v2.8.0 +│ │ │ │ ├── phf v0.11.3 (*) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ ├── regex v1.12.3 +│ │ │ │ │ ├── aho-corasick v1.1.4 +│ │ │ │ │ │ └── memchr v2.8.0 +│ │ │ │ │ ├── memchr v2.8.0 +│ │ │ │ │ ├── regex-automata v0.4.14 +│ │ │ │ │ │ ├── aho-corasick v1.1.4 (*) +│ │ │ │ │ │ ├── memchr v2.8.0 +│ │ │ │ │ │ └── regex-syntax v0.8.9 +│ │ │ │ │ └── regex-syntax v0.8.9 +│ │ │ │ ├── schemars v0.8.22 +│ │ │ │ │ ├── dyn-clone v1.0.20 +│ │ │ │ │ ├── indexmap v1.9.3 +│ │ │ │ │ │ ├── hashbrown v0.12.3 +│ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── autocfg v1.5.0 +│ │ │ │ │ ├── schemars_derive v0.8.22 (proc-macro) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ ├── serde_derive_internals v0.29.1 +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ ├── serde_json v1.0.149 (*) +│ │ │ │ │ ├── url v2.5.8 +│ │ │ │ │ │ ├── form_urlencoded v1.2.2 +│ │ │ │ │ │ │ └── percent-encoding v2.3.2 +│ │ │ │ │ │ ├── idna v1.1.0 +│ │ │ │ │ │ │ ├── idna_adapter v1.2.1 +│ │ │ │ │ │ │ │ ├── icu_normalizer v2.1.1 +│ │ │ │ │ │ │ │ │ ├── icu_collections v2.1.1 +│ │ │ │ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) +│ │ │ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ │ │ │ ├── potential_utf v0.1.4 +│ │ │ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 +│ │ │ │ │ │ │ │ │ │ │ ├── yoke v0.8.1 +│ │ │ │ │ │ │ │ │ │ │ │ ├── stable_deref_trait v1.2.1 +│ │ │ │ │ │ │ │ │ │ │ │ ├── yoke-derive v0.8.1 (proc-macro) +│ │ │ │ │ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ │ │ │ │ │ ├── syn v2.0.117 (*) +│ │ │ │ │ │ │ │ │ │ │ │ │ └── synstructure v0.13.2 +│ │ │ │ │ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ │ │ │ │ │ └── zerofrom v0.1.6 +│ │ │ │ │ │ │ │ │ │ │ │ └── zerofrom-derive v0.1.6 (proc-macro) +│ │ │ │ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ │ │ │ │ ├── syn v2.0.117 (*) +│ │ │ │ │ │ │ │ │ │ │ │ └── synstructure v0.13.2 (*) +│ │ │ │ │ │ │ │ │ │ │ ├── zerofrom v0.1.6 (*) +│ │ │ │ │ │ │ │ │ │ │ └── zerovec-derive v0.11.2 (proc-macro) +│ │ │ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ │ │ │ ├── yoke v0.8.1 (*) +│ │ │ │ │ │ │ │ │ │ ├── zerofrom v0.1.6 (*) +│ │ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ │ │ ├── icu_normalizer_data v2.1.1 +│ │ │ │ │ │ │ │ │ ├── icu_provider v2.1.1 +│ │ │ │ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*) +│ │ │ │ │ │ │ │ │ │ ├── icu_locale_core v2.1.1 +│ │ │ │ │ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*) +│ │ │ │ │ │ │ │ │ │ │ ├── litemap v0.8.1 +│ │ │ │ │ │ │ │ │ │ │ ├── tinystr v0.8.2 +│ │ │ │ │ │ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*) +│ │ │ │ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ │ │ │ │ ├── writeable v0.6.2 +│ │ │ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ │ │ │ ├── writeable v0.6.2 +│ │ │ │ │ │ │ │ │ │ ├── yoke v0.8.1 (*) +│ │ │ │ │ │ │ │ │ │ ├── zerofrom v0.1.6 (*) +│ │ │ │ │ │ │ │ │ │ ├── zerotrie v0.2.3 +│ │ │ │ │ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*) +│ │ │ │ │ │ │ │ │ │ │ ├── yoke v0.8.1 (*) +│ │ │ │ │ │ │ │ │ │ │ └── zerofrom v0.1.6 (*) +│ │ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ │ │ ├── smallvec v1.15.1 +│ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ │ └── icu_properties v2.1.2 +│ │ │ │ │ │ │ │ ├── icu_collections v2.1.1 (*) +│ │ │ │ │ │ │ │ ├── icu_locale_core v2.1.1 (*) +│ │ │ │ │ │ │ │ ├── icu_properties_data v2.1.2 +│ │ │ │ │ │ │ │ ├── icu_provider v2.1.1 (*) +│ │ │ │ │ │ │ │ ├── zerotrie v0.2.3 (*) +│ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ ├── smallvec v1.15.1 +│ │ │ │ │ │ │ └── utf8_iter v1.0.4 +│ │ │ │ │ │ ├── percent-encoding v2.3.2 +│ │ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ │ └── serde_derive v1.0.228 (proc-macro) (*) +│ │ │ │ │ └── uuid v1.21.0 (*) +│ │ │ │ ├── semver v1.0.27 (*) +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ ├── serde-untagged v0.1.9 +│ │ │ │ │ ├── erased-serde v0.4.9 +│ │ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ │ └── typeid v1.0.3 +│ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ └── typeid v1.0.3 +│ │ │ │ ├── serde_json v1.0.149 (*) +│ │ │ │ ├── serde_with v3.16.1 (*) +│ │ │ │ ├── thiserror v2.0.18 (*) +│ │ │ │ ├── toml v0.9.12+spec-1.1.0 +│ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ ├── serde_spanned v1.0.4 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── toml_datetime v0.7.5+spec-1.1.0 (*) +│ │ │ │ │ ├── toml_parser v1.0.9+spec-1.1.0 (*) +│ │ │ │ │ ├── toml_writer v1.0.6+spec-1.1.0 +│ │ │ │ │ └── winnow v0.7.14 +│ │ │ │ ├── url v2.5.8 (*) +│ │ │ │ ├── urlpattern v0.3.0 +│ │ │ │ │ ├── regex v1.12.3 (*) +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ ├── unic-ucd-ident v0.9.0 +│ │ │ │ │ │ ├── unic-char-property v0.9.0 +│ │ │ │ │ │ │ └── unic-char-range v0.9.0 +│ │ │ │ │ │ ├── unic-char-range v0.9.0 +│ │ │ │ │ │ └── unic-ucd-version v0.9.0 +│ │ │ │ │ │ └── unic-common v0.9.0 +│ │ │ │ │ └── url v2.5.8 (*) +│ │ │ │ ├── uuid v1.21.0 (*) +│ │ │ │ └── walkdir v2.5.0 +│ │ │ │ └── same-file v1.0.6 +│ │ │ ├── thiserror v2.0.18 (*) +│ │ │ ├── url v2.5.8 (*) +│ │ │ ├── uuid v1.21.0 (*) +│ │ │ └── walkdir v2.5.0 (*) +│ │ └── tauri-utils v2.8.2 (*) +│ ├── tauri-runtime v2.10.0 +│ │ ├── cookie v0.18.1 (*) +│ │ ├── dpi v0.1.2 (*) +│ │ ├── gtk v0.18.2 (*) +│ │ ├── http v1.4.0 (*) +│ │ ├── raw-window-handle v0.6.2 +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_json v1.0.149 (*) +│ │ ├── tauri-utils v2.8.2 +│ │ │ ├── anyhow v1.0.102 +│ │ │ ├── brotli v8.0.2 (*) +│ │ │ ├── ctor v0.2.9 (proc-macro) (*) +│ │ │ ├── dunce v1.0.5 +│ │ │ ├── glob v0.3.3 +│ │ │ ├── http v1.4.0 (*) +│ │ │ ├── infer v0.19.0 (*) +│ │ │ ├── json-patch v3.0.1 (*) +│ │ │ ├── log v0.4.29 +│ │ │ ├── memchr v2.8.0 +│ │ │ ├── phf v0.11.3 (*) +│ │ │ ├── regex v1.12.3 (*) +│ │ │ ├── semver v1.0.27 +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── serde-untagged v0.1.9 (*) +│ │ │ ├── serde_json v1.0.149 (*) +│ │ │ ├── serde_with v3.16.1 (*) +│ │ │ ├── thiserror v2.0.18 (*) +│ │ │ ├── toml v0.9.12+spec-1.1.0 (*) +│ │ │ ├── url v2.5.8 (*) +│ │ │ ├── urlpattern v0.3.0 (*) +│ │ │ ├── uuid v1.21.0 +│ │ │ │ └── serde_core v1.0.228 +│ │ │ └── walkdir v2.5.0 (*) +│ │ ├── thiserror v2.0.18 (*) +│ │ ├── url v2.5.8 (*) +│ │ └── webkit2gtk v2.0.2 +│ │ ├── bitflags v1.3.2 +│ │ ├── cairo-rs v0.18.5 (*) +│ │ ├── gdk v0.18.2 (*) +│ │ ├── gdk-sys v0.18.2 (*) +│ │ ├── gio v0.18.4 (*) +│ │ ├── gio-sys v0.18.1 (*) +│ │ ├── glib v0.18.5 (*) +│ │ ├── glib-sys v0.18.1 (*) +│ │ ├── gobject-sys v0.18.0 (*) +│ │ ├── gtk v0.18.2 (*) +│ │ ├── gtk-sys v0.18.2 (*) +│ │ ├── javascriptcore-rs v1.1.2 +│ │ │ ├── bitflags v1.3.2 +│ │ │ ├── glib v0.18.5 (*) +│ │ │ └── javascriptcore-rs-sys v1.1.1 +│ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ └── libc v0.2.182 +│ │ │ [build-dependencies] +│ │ │ └── system-deps v6.2.2 (*) +│ │ ├── libc v0.2.182 +│ │ ├── once_cell v1.21.3 +│ │ ├── soup3 v0.5.0 +│ │ │ ├── futures-channel v0.3.32 (*) +│ │ │ ├── gio v0.18.4 (*) +│ │ │ ├── glib v0.18.5 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ └── soup3-sys v0.5.0 +│ │ │ ├── gio-sys v0.18.1 (*) +│ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ └── libc v0.2.182 +│ │ │ [build-dependencies] +│ │ │ └── system-deps v6.2.2 (*) +│ │ └── webkit2gtk-sys v2.0.2 +│ │ ├── bitflags v1.3.2 +│ │ ├── cairo-sys-rs v0.18.2 (*) +│ │ ├── gdk-sys v0.18.2 (*) +│ │ ├── gio-sys v0.18.1 (*) +│ │ ├── glib-sys v0.18.1 (*) +│ │ ├── gobject-sys v0.18.0 (*) +│ │ ├── gtk-sys v0.18.2 (*) +│ │ ├── javascriptcore-rs-sys v1.1.1 (*) +│ │ ├── libc v0.2.182 +│ │ └── soup3-sys v0.5.0 (*) +│ │ [build-dependencies] +│ │ ├── pkg-config v0.3.32 +│ │ └── system-deps v6.2.2 (*) +│ ├── tauri-runtime-wry v2.10.0 +│ │ ├── gtk v0.18.2 (*) +│ │ ├── http v1.4.0 (*) +│ │ ├── log v0.4.29 +│ │ ├── percent-encoding v2.3.2 +│ │ ├── raw-window-handle v0.6.2 +│ │ ├── tao v0.34.5 +│ │ │ ├── bitflags v2.11.0 (*) +│ │ │ ├── crossbeam-channel v0.5.15 (*) +│ │ │ ├── dlopen2 v0.8.2 +│ │ │ │ ├── dlopen2_derive v0.4.3 (proc-macro) +│ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── libc v0.2.182 +│ │ │ │ └── once_cell v1.21.3 +│ │ │ ├── dpi v0.1.2 (*) +│ │ │ ├── gdkwayland-sys v0.18.2 +│ │ │ │ ├── gdk-sys v0.18.2 (*) +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ └── libc v0.2.182 +│ │ │ │ [build-dependencies] +│ │ │ │ ├── pkg-config v0.3.32 +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ ├── gdkx11-sys v0.18.2 +│ │ │ │ ├── gdk-sys v0.18.2 (*) +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ ├── libc v0.2.182 +│ │ │ │ └── x11 v2.21.0 +│ │ │ │ └── libc v0.2.182 +│ │ │ │ [build-dependencies] +│ │ │ │ └── pkg-config v0.3.32 +│ │ │ │ [build-dependencies] +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ ├── gtk v0.18.2 (*) +│ │ │ ├── lazy_static v1.5.0 +│ │ │ ├── libc v0.2.182 +│ │ │ ├── log v0.4.29 +│ │ │ ├── parking_lot v0.12.5 (*) +│ │ │ ├── raw-window-handle v0.6.2 +│ │ │ ├── url v2.5.8 (*) +│ │ │ └── x11-dl v2.21.0 +│ │ │ ├── libc v0.2.182 +│ │ │ └── once_cell v1.21.3 +│ │ │ [build-dependencies] +│ │ │ └── pkg-config v0.3.32 +│ │ ├── tauri-runtime v2.10.0 (*) +│ │ ├── tauri-utils v2.8.2 (*) +│ │ ├── url v2.5.8 (*) +│ │ ├── webkit2gtk v2.0.2 (*) +│ │ └── wry v0.54.2 +│ │ ├── cookie v0.18.1 (*) +│ │ ├── dirs v6.0.0 (*) +│ │ ├── dpi v0.1.2 (*) +│ │ ├── gdkx11 v0.18.2 +│ │ │ ├── gdk v0.18.2 (*) +│ │ │ ├── gdkx11-sys v0.18.2 (*) +│ │ │ ├── gio v0.18.4 (*) +│ │ │ ├── glib v0.18.5 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ └── x11 v2.21.0 (*) +│ │ ├── gtk v0.18.2 (*) +│ │ ├── http v1.4.0 (*) +│ │ ├── javascriptcore-rs v1.1.2 (*) +│ │ ├── once_cell v1.21.3 +│ │ ├── percent-encoding v2.3.2 +│ │ ├── raw-window-handle v0.6.2 +│ │ ├── soup3 v0.5.0 (*) +│ │ ├── thiserror v2.0.18 (*) +│ │ ├── webkit2gtk v2.0.2 (*) +│ │ ├── webkit2gtk-sys v2.0.2 (*) +│ │ └── x11-dl v2.21.0 (*) +│ ├── tauri-utils v2.8.2 (*) +│ ├── thiserror v2.0.18 (*) +│ ├── tokio v1.49.0 +│ │ ├── bytes v1.11.1 (*) +│ │ └── pin-project-lite v0.2.16 +│ ├── url v2.5.8 (*) +│ └── webkit2gtk v2.0.2 (*) +│ [build-dependencies] +│ ├── glob v0.3.3 +│ ├── heck v0.5.0 +│ ├── tauri-build v2.5.5 +│ │ ├── anyhow v1.0.102 +│ │ ├── cargo_toml v0.22.3 +│ │ │ ├── serde v1.0.228 (*) +│ │ │ └── toml v0.9.12+spec-1.1.0 (*) +│ │ ├── dirs v6.0.0 (*) +│ │ ├── glob v0.3.3 +│ │ ├── heck v0.5.0 +│ │ ├── json-patch v3.0.1 (*) +│ │ ├── schemars v0.8.22 (*) +│ │ ├── semver v1.0.27 (*) +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_json v1.0.149 (*) +│ │ ├── tauri-utils v2.8.2 (*) +│ │ ├── tauri-winres v0.3.5 +│ │ │ ├── dunce v1.0.5 +│ │ │ ├── embed-resource v3.0.6 +│ │ │ │ ├── cc v1.2.56 +│ │ │ │ │ ├── find-msvc-tools v0.1.9 +│ │ │ │ │ └── shlex v1.3.0 +│ │ │ │ ├── memchr v2.8.0 +│ │ │ │ ├── rustc_version v0.4.1 (*) +│ │ │ │ └── toml v0.9.12+spec-1.1.0 (*) +│ │ │ └── toml v0.9.12+spec-1.1.0 (*) +│ │ ├── toml v0.9.12+spec-1.1.0 (*) +│ │ └── walkdir v2.5.0 (*) +│ └── tauri-utils v2.8.2 (*) +├── tauri-plugin-dialog v2.6.0 +│ ├── log v0.4.29 +│ ├── raw-window-handle v0.6.2 +│ ├── rfd v0.16.0 +│ │ ├── glib-sys v0.18.1 (*) +│ │ ├── gobject-sys v0.18.0 (*) +│ │ ├── gtk-sys v0.18.2 (*) +│ │ ├── log v0.4.29 +│ │ └── raw-window-handle v0.6.2 +│ ├── serde v1.0.228 (*) +│ ├── serde_json v1.0.149 (*) +│ ├── tauri v2.10.2 (*) +│ ├── tauri-plugin-fs v2.4.5 +│ │ ├── anyhow v1.0.102 +│ │ ├── dunce v1.0.5 +│ │ ├── glob v0.3.3 +│ │ ├── percent-encoding v2.3.2 +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_json v1.0.149 (*) +│ │ ├── serde_repr v0.1.20 (proc-macro) (*) +│ │ ├── tauri v2.10.2 (*) +│ │ ├── thiserror v2.0.18 (*) +│ │ └── url v2.5.8 (*) +│ │ [build-dependencies] +│ │ ├── schemars v0.8.22 (*) +│ │ ├── serde v1.0.228 (*) +│ │ ├── tauri-plugin v2.5.3 +│ │ │ ├── anyhow v1.0.102 +│ │ │ ├── glob v0.3.3 +│ │ │ ├── schemars v0.8.22 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── serde_json v1.0.149 (*) +│ │ │ ├── tauri-utils v2.8.2 (*) +│ │ │ ├── toml v0.9.12+spec-1.1.0 (*) +│ │ │ └── walkdir v2.5.0 (*) +│ │ ├── tauri-utils v2.8.2 (*) +│ │ └── toml v0.9.12+spec-1.1.0 (*) +│ ├── thiserror v2.0.18 (*) +│ └── url v2.5.8 (*) +│ [build-dependencies] +│ └── tauri-plugin v2.5.3 (*) +├── tauri-plugin-fs v2.4.5 (*) +├── time v0.3.47 (*) +├── tree_hash v0.12.1 +│ ├── alloy-primitives v1.5.7 (*) +│ ├── ethereum_hashing v0.8.0 +│ │ ├── cpufeatures v0.2.17 +│ │ ├── ring v0.17.14 +│ │ │ ├── cfg-if v1.0.4 +│ │ │ ├── getrandom v0.2.17 (*) +│ │ │ └── untrusted v0.9.0 +│ │ │ [build-dependencies] +│ │ │ └── cc v1.2.56 (*) +│ │ └── sha2 v0.10.9 (*) +│ ├── ethereum_ssz v0.10.1 +│ │ ├── alloy-primitives v1.5.7 (*) +│ │ ├── ethereum_serde_utils v0.8.0 (*) +│ │ ├── itertools v0.14.0 (*) +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_derive v1.0.228 (proc-macro) (*) +│ │ ├── smallvec v1.15.1 (*) +│ │ └── typenum v1.19.0 +│ ├── smallvec v1.15.1 (*) +│ └── typenum v1.19.0 +├── typenum v1.19.0 +└── window-vibrancy v0.6.0 + └── raw-window-handle v0.6.2 +[build-dependencies] +└── tauri-build v2.5.5 (*) +``` diff --git a/docs/audit/dependency-footprint.md b/docs/audit/dependency-footprint.md new file mode 100644 index 00000000..87837d1b --- /dev/null +++ b/docs/audit/dependency-footprint.md @@ -0,0 +1,2129 @@ +# Dependency Footprint + +Generated by `scripts/audit/deps.sh`. + +## Inputs + +- `bun.lock` SHA-256: `d78b3a1b2e6d6daa607f8d711bffaef2e74e639c7eff66bd05c12dc2de6aeb0f` +- `apps/desktop/src-tauri/Cargo.lock`: `present` + +## JavaScript Dependency Tree (bun list --all) + +```text +/workspaces/mission-b3dce69f/repo node_modules +├── @adraffy/ens-normalize@1.11.1 +├── @alloc/quick-lru@5.2.0 +├── @babel/code-frame@7.29.0 +├── @babel/compat-data@7.29.0 +├── @babel/core@7.29.0 +├── @babel/generator@7.29.1 +├── @babel/helper-compilation-targets@7.28.6 +├── @babel/helper-globals@7.28.0 +├── @babel/helper-module-imports@7.28.6 +├── @babel/helper-module-transforms@7.28.6 +├── @babel/helper-plugin-utils@7.28.6 +├── @babel/helper-string-parser@7.27.1 +├── @babel/helper-validator-identifier@7.28.5 +├── @babel/helper-validator-option@7.27.1 +├── @babel/helpers@7.28.6 +├── @babel/parser@7.29.0 +├── @babel/plugin-transform-react-jsx-self@7.27.1 +├── @babel/plugin-transform-react-jsx-source@7.27.1 +├── @babel/template@7.28.6 +├── @babel/traverse@7.29.0 +├── @babel/types@7.29.0 +├── @emnapi/core@1.8.1 +├── @emnapi/runtime@1.8.1 +├── @emnapi/wasi-threads@1.1.0 +├── @esbuild/aix-ppc64@0.21.5 +├── @esbuild/android-arm@0.21.5 +├── @esbuild/android-arm64@0.21.5 +├── @esbuild/android-x64@0.21.5 +├── @esbuild/darwin-arm64@0.21.5 +├── @esbuild/darwin-x64@0.21.5 +├── @esbuild/freebsd-arm64@0.21.5 +├── @esbuild/freebsd-x64@0.21.5 +├── @esbuild/linux-arm@0.21.5 +├── @esbuild/linux-arm64@0.21.5 +├── @esbuild/linux-ia32@0.21.5 +├── @esbuild/linux-loong64@0.21.5 +├── @esbuild/linux-mips64el@0.21.5 +├── @esbuild/linux-ppc64@0.21.5 +├── @esbuild/linux-riscv64@0.21.5 +├── @esbuild/linux-s390x@0.21.5 +├── @esbuild/linux-x64@0.21.5 +├── @esbuild/netbsd-arm64@0.27.3 +├── @esbuild/netbsd-x64@0.21.5 +├── @esbuild/openbsd-arm64@0.27.3 +├── @esbuild/openbsd-x64@0.21.5 +├── @esbuild/openharmony-arm64@0.27.3 +├── @esbuild/sunos-x64@0.21.5 +├── @esbuild/win32-arm64@0.21.5 +├── @esbuild/win32-ia32@0.21.5 +├── @esbuild/win32-x64@0.21.5 +├── @eslint-community/eslint-utils@4.9.1 +├── @eslint-community/regexpp@4.12.2 +├── @eslint/eslintrc@2.1.4 +├── @eslint/js@8.57.1 +├── @humanwhocodes/config-array@0.13.0 +├── @humanwhocodes/module-importer@1.0.1 +├── @humanwhocodes/object-schema@2.0.3 +├── @isaacs/cliui@8.0.2 +│ └── strip-ansi@7.1.2 +│ └── ansi-regex@6.2.2 +├── @jridgewell/gen-mapping@0.3.13 +├── @jridgewell/remapping@2.3.5 +├── @jridgewell/resolve-uri@3.1.2 +├── @jridgewell/sourcemap-codec@1.5.5 +├── @jridgewell/trace-mapping@0.3.31 +├── @napi-rs/wasm-runtime@0.2.12 +├── @next/env@14.2.35 +├── @next/eslint-plugin-next@14.2.35 +├── @next/swc-darwin-arm64@14.2.33 +├── @next/swc-darwin-x64@14.2.33 +├── @next/swc-linux-arm64-gnu@14.2.33 +├── @next/swc-linux-arm64-musl@14.2.33 +├── @next/swc-linux-x64-gnu@14.2.33 +├── @next/swc-linux-x64-musl@14.2.33 +├── @next/swc-win32-arm64-msvc@14.2.33 +├── @next/swc-win32-ia32-msvc@14.2.33 +├── @next/swc-win32-x64-msvc@14.2.33 +├── @noble/ciphers@1.3.0 +├── @noble/curves@1.9.1 +├── @noble/hashes@1.8.0 +├── @nodelib/fs.scandir@2.1.5 +├── @nodelib/fs.stat@2.0.5 +├── @nodelib/fs.walk@1.2.8 +├── @nolyfill/is-core-module@1.0.39 +├── @pkgjs/parseargs@0.11.0 +├── @rolldown/pluginutils@1.0.0-beta.27 +├── @rollup/rollup-android-arm-eabi@4.57.1 +├── @rollup/rollup-android-arm64@4.57.1 +├── @rollup/rollup-darwin-arm64@4.57.1 +├── @rollup/rollup-darwin-x64@4.57.1 +├── @rollup/rollup-freebsd-arm64@4.57.1 +├── @rollup/rollup-freebsd-x64@4.57.1 +├── @rollup/rollup-linux-arm-gnueabihf@4.57.1 +├── @rollup/rollup-linux-arm-musleabihf@4.57.1 +├── @rollup/rollup-linux-arm64-gnu@4.57.1 +├── @rollup/rollup-linux-arm64-musl@4.57.1 +├── @rollup/rollup-linux-loong64-gnu@4.57.1 +├── @rollup/rollup-linux-loong64-musl@4.57.1 +├── @rollup/rollup-linux-ppc64-gnu@4.57.1 +├── @rollup/rollup-linux-ppc64-musl@4.57.1 +├── @rollup/rollup-linux-riscv64-gnu@4.57.1 +├── @rollup/rollup-linux-riscv64-musl@4.57.1 +├── @rollup/rollup-linux-s390x-gnu@4.57.1 +├── @rollup/rollup-linux-x64-gnu@4.57.1 +├── @rollup/rollup-linux-x64-musl@4.57.1 +├── @rollup/rollup-openbsd-x64@4.57.1 +├── @rollup/rollup-openharmony-arm64@4.57.1 +├── @rollup/rollup-win32-arm64-msvc@4.57.1 +├── @rollup/rollup-win32-ia32-msvc@4.57.1 +├── @rollup/rollup-win32-x64-gnu@4.57.1 +├── @rollup/rollup-win32-x64-msvc@4.57.1 +├── @rtsao/scc@1.1.0 +├── @rushstack/eslint-patch@1.16.1 +├── @safelens/cli@workspace:packages/cli +├── @safelens/core@workspace:packages/core +├── @safelens/desktop@workspace:apps/desktop +├── @safelens/generator@workspace:apps/generator +│ └── @types/node@20.19.33 +│ └── undici-types@6.21.0 +├── @safelens/shared-theme@workspace:apps/shared-theme +├── @scure/base@1.2.6 +├── @scure/bip32@1.7.0 +├── @scure/bip39@1.6.0 +├── @standard-schema/spec@1.1.0 +├── @swc/counter@0.1.3 +├── @swc/helpers@0.5.5 +├── @tauri-apps/api@2.10.1 +├── @tauri-apps/cli@2.10.0 +├── @tauri-apps/cli-darwin-arm64@2.10.0 +├── @tauri-apps/cli-darwin-x64@2.10.0 +├── @tauri-apps/cli-linux-arm-gnueabihf@2.10.0 +├── @tauri-apps/cli-linux-arm64-gnu@2.10.0 +├── @tauri-apps/cli-linux-arm64-musl@2.10.0 +├── @tauri-apps/cli-linux-riscv64-gnu@2.10.0 +├── @tauri-apps/cli-linux-x64-gnu@2.10.0 +├── @tauri-apps/cli-linux-x64-musl@2.10.0 +├── @tauri-apps/cli-win32-arm64-msvc@2.10.0 +├── @tauri-apps/cli-win32-ia32-msvc@2.10.0 +├── @tauri-apps/cli-win32-x64-msvc@2.10.0 +├── @tauri-apps/plugin-dialog@2.6.0 +├── @tauri-apps/plugin-fs@2.4.5 +├── @tybys/wasm-util@0.10.1 +├── @types/babel__core@7.20.5 +├── @types/babel__generator@7.27.0 +├── @types/babel__template@7.4.4 +├── @types/babel__traverse@7.28.0 +├── @types/chai@5.2.3 +├── @types/deep-eql@4.0.2 +├── @types/estree@1.0.8 +├── @types/json5@0.0.29 +├── @types/node@25.3.0 +├── @types/prop-types@15.7.15 +├── @types/react@18.3.28 +├── @types/react-dom@18.3.7 +├── @typescript-eslint/eslint-plugin@8.56.0 +│ └── ignore@7.0.5 +├── @typescript-eslint/parser@8.56.0 +├── @typescript-eslint/project-service@8.56.0 +├── @typescript-eslint/scope-manager@8.56.0 +├── @typescript-eslint/tsconfig-utils@8.56.0 +├── @typescript-eslint/type-utils@8.56.0 +├── @typescript-eslint/types@8.56.0 +├── @typescript-eslint/typescript-estree@8.56.0 +│ ├── minimatch@9.0.5 +│ │ └── brace-expansion@2.0.2 +│ └── semver@7.7.4 +├── @typescript-eslint/utils@8.56.0 +├── @typescript-eslint/visitor-keys@8.56.0 +│ └── eslint-visitor-keys@5.0.1 +├── @ungap/structured-clone@1.3.0 +├── @unrs/resolver-binding-android-arm-eabi@1.11.1 +├── @unrs/resolver-binding-android-arm64@1.11.1 +├── @unrs/resolver-binding-darwin-arm64@1.11.1 +├── @unrs/resolver-binding-darwin-x64@1.11.1 +├── @unrs/resolver-binding-freebsd-x64@1.11.1 +├── @unrs/resolver-binding-linux-arm-gnueabihf@1.11.1 +├── @unrs/resolver-binding-linux-arm-musleabihf@1.11.1 +├── @unrs/resolver-binding-linux-arm64-gnu@1.11.1 +├── @unrs/resolver-binding-linux-arm64-musl@1.11.1 +├── @unrs/resolver-binding-linux-ppc64-gnu@1.11.1 +├── @unrs/resolver-binding-linux-riscv64-gnu@1.11.1 +├── @unrs/resolver-binding-linux-riscv64-musl@1.11.1 +├── @unrs/resolver-binding-linux-s390x-gnu@1.11.1 +├── @unrs/resolver-binding-linux-x64-gnu@1.11.1 +├── @unrs/resolver-binding-linux-x64-musl@1.11.1 +├── @unrs/resolver-binding-wasm32-wasi@1.11.1 +├── @unrs/resolver-binding-win32-arm64-msvc@1.11.1 +├── @unrs/resolver-binding-win32-ia32-msvc@1.11.1 +├── @unrs/resolver-binding-win32-x64-msvc@1.11.1 +├── @vitejs/plugin-react@4.7.0 +├── @vitest/expect@4.0.18 +├── @vitest/mocker@4.0.18 +│ └── vite@7.3.1 +│ └── esbuild@0.27.3 +│ ├── @esbuild/aix-ppc64@0.27.3 +│ ├── @esbuild/android-arm@0.27.3 +│ ├── @esbuild/android-arm64@0.27.3 +│ ├── @esbuild/android-x64@0.27.3 +│ ├── @esbuild/darwin-arm64@0.27.3 +│ ├── @esbuild/darwin-x64@0.27.3 +│ ├── @esbuild/freebsd-arm64@0.27.3 +│ ├── @esbuild/freebsd-x64@0.27.3 +│ ├── @esbuild/linux-arm@0.27.3 +│ ├── @esbuild/linux-arm64@0.27.3 +│ ├── @esbuild/linux-ia32@0.27.3 +│ ├── @esbuild/linux-loong64@0.27.3 +│ ├── @esbuild/linux-mips64el@0.27.3 +│ ├── @esbuild/linux-ppc64@0.27.3 +│ ├── @esbuild/linux-riscv64@0.27.3 +│ ├── @esbuild/linux-s390x@0.27.3 +│ ├── @esbuild/linux-x64@0.27.3 +│ ├── @esbuild/netbsd-x64@0.27.3 +│ ├── @esbuild/openbsd-x64@0.27.3 +│ ├── @esbuild/sunos-x64@0.27.3 +│ ├── @esbuild/win32-arm64@0.27.3 +│ ├── @esbuild/win32-ia32@0.27.3 +│ └── @esbuild/win32-x64@0.27.3 +├── @vitest/pretty-format@4.0.18 +├── @vitest/runner@4.0.18 +├── @vitest/snapshot@4.0.18 +├── @vitest/spy@4.0.18 +├── @vitest/utils@4.0.18 +├── abitype@1.2.3 +├── acorn@8.16.0 +├── acorn-jsx@5.3.2 +├── ajv@6.12.6 +├── ansi-regex@5.0.1 +├── ansi-styles@4.3.0 +├── any-promise@1.3.0 +├── anymatch@3.1.3 +│ └── picomatch@2.3.1 +├── arg@5.0.2 +├── argparse@2.0.1 +├── aria-query@5.3.2 +├── array-buffer-byte-length@1.0.2 +├── array-includes@3.1.9 +├── array.prototype.findlast@1.2.5 +├── array.prototype.findlastindex@1.2.6 +├── array.prototype.flat@1.3.3 +├── array.prototype.flatmap@1.3.3 +├── array.prototype.tosorted@1.1.4 +├── arraybuffer.prototype.slice@1.0.4 +├── assertion-error@2.0.1 +├── ast-types-flow@0.0.8 +├── async-function@1.0.0 +├── autoprefixer@10.4.24 +├── available-typed-arrays@1.0.7 +├── axe-core@4.11.1 +├── axobject-query@4.1.0 +├── balanced-match@1.0.2 +├── baseline-browser-mapping@2.9.19 +├── binary-extensions@2.3.0 +├── brace-expansion@1.1.12 +├── braces@3.0.3 +├── browserslist@4.28.1 +├── busboy@1.6.0 +├── call-bind@1.0.8 +├── call-bind-apply-helpers@1.0.2 +├── call-bound@1.0.4 +├── callsites@3.1.0 +├── camelcase-css@2.0.1 +├── caniuse-lite@1.0.30001769 +├── chai@6.2.2 +├── chalk@4.1.2 +├── chokidar@3.6.0 +│ └── glob-parent@5.1.2 +├── class-variance-authority@0.7.1 +├── client-only@0.0.1 +├── clsx@2.1.1 +├── color-convert@2.0.1 +├── color-name@1.1.4 +├── commander@4.1.1 +├── concat-map@0.0.1 +├── convert-source-map@2.0.0 +├── cross-spawn@7.0.6 +├── cssesc@3.0.0 +├── csstype@3.2.3 +├── damerau-levenshtein@1.0.8 +├── data-view-buffer@1.0.2 +├── data-view-byte-length@1.0.2 +├── data-view-byte-offset@1.0.1 +├── debug@4.4.3 +├── deep-is@0.1.4 +├── define-data-property@1.1.4 +├── define-properties@1.2.1 +├── detect-libc@2.1.2 +├── didyoumean@1.2.2 +├── dlv@1.1.3 +├── doctrine@3.0.0 +├── dunder-proto@1.0.1 +├── eastasianwidth@0.2.0 +├── electron-to-chromium@1.5.286 +├── emoji-regex@9.2.2 +├── es-abstract@1.24.1 +├── es-define-property@1.0.1 +├── es-errors@1.3.0 +├── es-iterator-helpers@1.2.2 +├── es-module-lexer@1.7.0 +├── es-object-atoms@1.1.1 +├── es-set-tostringtag@2.1.0 +├── es-shim-unscopables@1.1.0 +├── es-to-primitive@1.3.0 +├── esbuild@0.21.5 +├── escalade@3.2.0 +├── escape-string-regexp@4.0.0 +├── eslint@8.57.1 +├── eslint-config-next@14.2.35 +├── eslint-import-resolver-node@0.3.9 +│ └── debug@3.2.7 +├── eslint-import-resolver-typescript@3.10.1 +├── eslint-module-utils@2.12.1 +│ └── debug@3.2.7 +├── eslint-plugin-import@2.32.0 +│ ├── debug@3.2.7 +│ └── doctrine@2.1.0 +├── eslint-plugin-jsx-a11y@6.10.2 +├── eslint-plugin-react@7.37.5 +│ ├── doctrine@2.1.0 +│ └── resolve@2.0.0-next.5 +├── eslint-plugin-react-hooks@4.6.2 +├── eslint-scope@7.2.2 +├── eslint-visitor-keys@3.4.3 +├── espree@9.6.1 +├── esquery@1.7.0 +├── esrecurse@4.3.0 +├── estraverse@5.3.0 +├── estree-walker@3.0.3 +├── esutils@2.0.3 +├── eventemitter3@5.0.1 +├── expect-type@1.3.0 +├── fast-deep-equal@3.1.3 +├── fast-glob@3.3.3 +│ └── glob-parent@5.1.2 +├── fast-json-stable-stringify@2.1.0 +├── fast-levenshtein@2.0.6 +├── fastq@1.20.1 +├── fdir@6.5.0 +├── file-entry-cache@6.0.1 +├── fill-range@7.1.1 +├── find-up@5.0.0 +├── flat-cache@3.2.0 +├── flatted@3.3.3 +├── for-each@0.3.5 +├── foreground-child@3.3.1 +├── fraction.js@5.3.4 +├── fs.realpath@1.0.0 +├── fsevents@2.3.3 +├── function-bind@1.1.2 +├── function.prototype.name@1.1.8 +├── functions-have-names@1.2.3 +├── generator-function@2.0.1 +├── gensync@1.0.0-beta.2 +├── get-intrinsic@1.3.0 +├── get-proto@1.0.1 +├── get-symbol-description@1.1.0 +├── get-tsconfig@4.13.6 +├── glob@10.3.10 +│ └── minimatch@9.0.5 +│ └── brace-expansion@2.0.2 +├── glob-parent@6.0.2 +├── globals@13.24.0 +├── globalthis@1.0.4 +├── gopd@1.2.0 +├── graceful-fs@4.2.11 +├── graphemer@1.4.0 +├── has-bigints@1.1.0 +├── has-flag@4.0.0 +├── has-property-descriptors@1.0.2 +├── has-proto@1.2.0 +├── has-symbols@1.1.0 +├── has-tostringtag@1.0.2 +├── hasown@2.0.2 +├── ignore@5.3.2 +├── import-fresh@3.3.1 +├── imurmurhash@0.1.4 +├── inflight@1.0.6 +├── inherits@2.0.4 +├── internal-slot@1.1.0 +├── is-array-buffer@3.0.5 +├── is-async-function@2.1.1 +├── is-bigint@1.1.0 +├── is-binary-path@2.1.0 +├── is-boolean-object@1.2.2 +├── is-bun-module@2.0.0 +│ └── semver@7.7.4 +├── is-callable@1.2.7 +├── is-core-module@2.16.1 +├── is-data-view@1.0.2 +├── is-date-object@1.1.0 +├── is-extglob@2.1.1 +├── is-finalizationregistry@1.1.1 +├── is-fullwidth-code-point@3.0.0 +├── is-generator-function@1.1.2 +├── is-glob@4.0.3 +├── is-map@2.0.3 +├── is-negative-zero@2.0.3 +├── is-number@7.0.0 +├── is-number-object@1.1.1 +├── is-path-inside@3.0.3 +├── is-regex@1.2.1 +├── is-set@2.0.3 +├── is-shared-array-buffer@1.0.4 +├── is-string@1.1.1 +├── is-symbol@1.1.1 +├── is-typed-array@1.1.15 +├── is-weakmap@2.0.2 +├── is-weakref@1.1.1 +├── is-weakset@2.0.4 +├── isarray@2.0.5 +├── isexe@2.0.0 +├── isows@1.0.7 +├── iterator.prototype@1.1.5 +├── jackspeak@2.3.6 +├── jiti@1.21.7 +├── js-tokens@4.0.0 +├── js-yaml@4.1.1 +├── jsesc@3.1.0 +├── json-buffer@3.0.1 +├── json-schema-traverse@0.4.1 +├── json-stable-stringify-without-jsonify@1.0.1 +├── json5@2.2.3 +├── jsx-ast-utils@3.3.5 +├── keyv@4.5.4 +├── language-subtag-registry@0.3.23 +├── language-tags@1.0.9 +├── levn@0.4.1 +├── lightningcss@1.31.1 +├── lightningcss-android-arm64@1.31.1 +├── lightningcss-darwin-arm64@1.31.1 +├── lightningcss-darwin-x64@1.31.1 +├── lightningcss-freebsd-x64@1.31.1 +├── lightningcss-linux-arm-gnueabihf@1.31.1 +├── lightningcss-linux-arm64-gnu@1.31.1 +├── lightningcss-linux-arm64-musl@1.31.1 +├── lightningcss-linux-x64-gnu@1.31.1 +├── lightningcss-linux-x64-musl@1.31.1 +├── lightningcss-win32-arm64-msvc@1.31.1 +├── lightningcss-win32-x64-msvc@1.31.1 +├── lilconfig@3.1.3 +├── lines-and-columns@1.2.4 +├── locate-path@6.0.0 +├── lodash.merge@4.6.2 +├── loose-envify@1.4.0 +├── lru-cache@5.1.1 +├── lucide-react@0.454.0 +├── magic-string@0.30.21 +├── math-intrinsics@1.1.0 +├── merge2@1.4.1 +├── micromatch@4.0.8 +│ └── picomatch@2.3.1 +├── minimatch@3.1.2 +├── minimist@1.2.8 +├── minipass@7.1.3 +├── ms@2.1.3 +├── mz@2.7.0 +├── nanoid@3.3.11 +├── napi-postinstall@0.3.4 +├── natural-compare@1.4.0 +├── next@14.2.35 +│ └── postcss@8.4.31 +├── node-releases@2.0.27 +├── normalize-path@3.0.0 +├── object-assign@4.1.1 +├── object-hash@3.0.0 +├── object-inspect@1.13.4 +├── object-keys@1.1.1 +├── object.assign@4.1.7 +├── object.entries@1.1.9 +├── object.fromentries@2.0.8 +├── object.groupby@1.0.3 +├── object.values@1.2.1 +├── obug@2.1.1 +├── once@1.4.0 +├── optionator@0.9.4 +├── own-keys@1.0.1 +├── ox@0.12.1 +├── p-limit@3.1.0 +├── p-locate@5.0.0 +├── parent-module@1.0.1 +├── path-exists@4.0.0 +├── path-is-absolute@1.0.1 +├── path-key@3.1.1 +├── path-parse@1.0.7 +├── path-scurry@1.11.1 +│ └── lru-cache@10.4.3 +├── pathe@2.0.3 +├── picocolors@1.1.1 +├── picomatch@4.0.3 +├── pify@2.3.0 +├── pirates@4.0.7 +├── possible-typed-array-names@1.1.0 +├── postcss@8.5.6 +├── postcss-import@15.1.0 +├── postcss-js@4.1.0 +├── postcss-load-config@6.0.1 +├── postcss-nested@6.2.0 +├── postcss-selector-parser@6.1.2 +├── postcss-value-parser@4.2.0 +├── prelude-ls@1.2.1 +├── prop-types@15.8.1 +├── punycode@2.3.1 +├── queue-microtask@1.2.3 +├── react@18.3.1 +├── react-dom@18.3.1 +├── react-is@16.13.1 +├── react-refresh@0.17.0 +├── read-cache@1.0.0 +├── readdirp@3.6.0 +│ └── picomatch@2.3.1 +├── reflect.getprototypeof@1.0.10 +├── regexp.prototype.flags@1.5.4 +├── resolve@1.22.11 +├── resolve-from@4.0.0 +├── resolve-pkg-maps@1.0.0 +├── reusify@1.1.0 +├── rimraf@3.0.2 +│ └── glob@7.2.3 +├── rollup@4.57.1 +├── run-parallel@1.2.0 +├── safe-array-concat@1.1.3 +├── safe-push-apply@1.0.0 +├── safe-regex-test@1.1.0 +├── scheduler@0.23.2 +├── semver@6.3.1 +├── set-function-length@1.2.2 +├── set-function-name@2.0.2 +├── set-proto@1.0.0 +├── shebang-command@2.0.0 +├── shebang-regex@3.0.0 +├── side-channel@1.1.0 +├── side-channel-list@1.0.0 +├── side-channel-map@1.0.1 +├── side-channel-weakmap@1.0.2 +├── siginfo@2.0.0 +├── signal-exit@4.1.0 +├── source-map-js@1.2.1 +├── stable-hash@0.0.5 +├── stackback@0.0.2 +├── std-env@3.10.0 +├── stop-iteration-iterator@1.1.0 +├── streamsearch@1.1.0 +├── string-width@5.1.2 +│ └── strip-ansi@7.1.2 +│ └── ansi-regex@6.2.2 +├── string-width-cjs@4.2.3 +│ └── emoji-regex@8.0.0 +├── string.prototype.includes@2.0.1 +├── string.prototype.matchall@4.0.12 +├── string.prototype.repeat@1.0.0 +├── string.prototype.trim@1.2.10 +├── string.prototype.trimend@1.0.9 +├── string.prototype.trimstart@1.0.8 +├── strip-ansi@6.0.1 +├── strip-ansi-cjs@6.0.1 +├── strip-bom@3.0.0 +├── strip-json-comments@3.1.1 +├── styled-jsx@5.1.1 +├── sucrase@3.35.1 +├── supports-color@7.2.0 +├── supports-preserve-symlinks-flag@1.0.0 +├── tailwind-merge@2.6.1 +├── tailwindcss@3.4.19 +├── text-table@0.2.0 +├── thenify@3.3.1 +├── thenify-all@1.6.0 +├── tinybench@2.9.0 +├── tinyexec@1.0.2 +├── tinyglobby@0.2.15 +├── tinyrainbow@3.0.3 +├── to-regex-range@5.0.1 +├── ts-api-utils@2.4.0 +├── ts-interface-checker@0.1.13 +├── tsconfig-paths@3.15.0 +│ └── json5@1.0.2 +├── tslib@2.8.1 +├── type-check@0.4.0 +├── type-fest@0.20.2 +├── typed-array-buffer@1.0.3 +├── typed-array-byte-length@1.0.3 +├── typed-array-byte-offset@1.0.4 +├── typed-array-length@1.0.7 +├── typescript@5.9.3 +├── unbox-primitive@1.1.0 +├── undici-types@7.18.2 +├── unrs-resolver@1.11.1 +├── update-browserslist-db@1.2.3 +├── uri-js@4.4.1 +├── util-deprecate@1.0.2 +├── viem@2.45.3 +├── vite@5.4.21 +├── vitest@4.0.18 +│ └── vite@7.3.1 +│ └── esbuild@0.27.3 +│ ├── @esbuild/aix-ppc64@0.27.3 +│ ├── @esbuild/android-arm@0.27.3 +│ ├── @esbuild/android-arm64@0.27.3 +│ ├── @esbuild/android-x64@0.27.3 +│ ├── @esbuild/darwin-arm64@0.27.3 +│ ├── @esbuild/darwin-x64@0.27.3 +│ ├── @esbuild/freebsd-arm64@0.27.3 +│ ├── @esbuild/freebsd-x64@0.27.3 +│ ├── @esbuild/linux-arm@0.27.3 +│ ├── @esbuild/linux-arm64@0.27.3 +│ ├── @esbuild/linux-ia32@0.27.3 +│ ├── @esbuild/linux-loong64@0.27.3 +│ ├── @esbuild/linux-mips64el@0.27.3 +│ ├── @esbuild/linux-ppc64@0.27.3 +│ ├── @esbuild/linux-riscv64@0.27.3 +│ ├── @esbuild/linux-s390x@0.27.3 +│ ├── @esbuild/linux-x64@0.27.3 +│ ├── @esbuild/netbsd-x64@0.27.3 +│ ├── @esbuild/openbsd-x64@0.27.3 +│ ├── @esbuild/sunos-x64@0.27.3 +│ ├── @esbuild/win32-arm64@0.27.3 +│ ├── @esbuild/win32-ia32@0.27.3 +│ └── @esbuild/win32-x64@0.27.3 +├── which@2.0.2 +├── which-boxed-primitive@1.1.1 +├── which-builtin-type@1.2.1 +├── which-collection@1.0.2 +├── which-typed-array@1.1.20 +├── why-is-node-running@2.3.0 +├── word-wrap@1.2.5 +├── wrap-ansi@8.1.0 +│ ├── ansi-styles@6.2.3 +│ └── strip-ansi@7.1.2 +│ └── ansi-regex@6.2.2 +├── wrap-ansi-cjs@7.0.0 +│ └── string-width@4.2.3 +│ └── emoji-regex@8.0.0 +├── wrappy@1.0.2 +├── ws@8.18.3 +├── yallist@3.1.1 +├── yocto-queue@0.1.0 +└── zod@4.3.6 +``` + +## Rust Dependency Tree (cargo tree for safelens-desktop) + +```text +safelens-desktop v0.4.0 (/workspaces/mission-b3dce69f/repo/apps/desktop/src-tauri) +├── alloy v1.7.3 +│ ├── alloy-consensus v1.7.3 +│ │ ├── alloy-eips v1.7.3 +│ │ │ ├── alloy-eip2124 v0.2.0 +│ │ │ │ ├── alloy-primitives v1.5.7 +│ │ │ │ │ ├── alloy-rlp v0.3.13 +│ │ │ │ │ │ ├── alloy-rlp-derive v0.3.13 (proc-macro) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 +│ │ │ │ │ │ │ │ └── unicode-ident v1.0.24 +│ │ │ │ │ │ │ ├── quote v1.0.44 +│ │ │ │ │ │ │ │ └── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── unicode-ident v1.0.24 +│ │ │ │ │ │ ├── arrayvec v0.7.6 +│ │ │ │ │ │ │ └── serde v1.0.228 +│ │ │ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ │ │ └── serde_derive v1.0.228 (proc-macro) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ └── bytes v1.11.1 +│ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ ├── bytes v1.11.1 (*) +│ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ ├── const-hex v1.17.0 +│ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ ├── cpufeatures v0.2.17 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── derive_more v2.1.1 +│ │ │ │ │ │ └── derive_more-impl v2.1.1 (proc-macro) +│ │ │ │ │ │ ├── convert_case v0.10.0 +│ │ │ │ │ │ │ └── unicode-segmentation v1.12.0 +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ ├── syn v2.0.117 (*) +│ │ │ │ │ │ └── unicode-xid v0.2.6 +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── rustc_version v0.4.1 +│ │ │ │ │ │ └── semver v1.0.27 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── foldhash v0.2.0 +│ │ │ │ │ ├── hashbrown v0.16.1 +│ │ │ │ │ │ ├── foldhash v0.2.0 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── indexmap v2.13.0 +│ │ │ │ │ │ ├── equivalent v1.0.2 +│ │ │ │ │ │ ├── hashbrown v0.16.1 (*) +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── itoa v1.0.17 +│ │ │ │ │ ├── k256 v0.13.4 +│ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ ├── ecdsa v0.16.9 +│ │ │ │ │ │ │ ├── der v0.7.10 +│ │ │ │ │ │ │ │ ├── const-oid v0.9.6 +│ │ │ │ │ │ │ │ └── zeroize v1.8.2 +│ │ │ │ │ │ │ │ └── zeroize_derive v1.4.3 (proc-macro) +│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ ├── digest v0.10.7 +│ │ │ │ │ │ │ │ ├── block-buffer v0.10.4 +│ │ │ │ │ │ │ │ │ └── generic-array v0.14.9 +│ │ │ │ │ │ │ │ │ ├── typenum v1.19.0 +│ │ │ │ │ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ │ │ │ └── version_check v0.9.5 +│ │ │ │ │ │ │ │ ├── const-oid v0.9.6 +│ │ │ │ │ │ │ │ ├── crypto-common v0.1.6 +│ │ │ │ │ │ │ │ │ ├── generic-array v0.14.9 (*) +│ │ │ │ │ │ │ │ │ └── typenum v1.19.0 +│ │ │ │ │ │ │ │ └── subtle v2.6.1 +│ │ │ │ │ │ │ ├── elliptic-curve v0.13.8 +│ │ │ │ │ │ │ │ ├── base16ct v0.2.0 +│ │ │ │ │ │ │ │ ├── crypto-bigint v0.5.5 +│ │ │ │ │ │ │ │ │ ├── generic-array v0.14.9 (*) +│ │ │ │ │ │ │ │ │ ├── rand_core v0.6.4 +│ │ │ │ │ │ │ │ │ │ └── getrandom v0.2.17 +│ │ │ │ │ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ │ │ │ │ ├── subtle v2.6.1 +│ │ │ │ │ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ │ │ │ │ ├── digest v0.10.7 (*) +│ │ │ │ │ │ │ │ ├── ff v0.13.1 +│ │ │ │ │ │ │ │ │ ├── bitvec v1.0.1 +│ │ │ │ │ │ │ │ │ │ ├── funty v2.0.0 +│ │ │ │ │ │ │ │ │ │ ├── radium v0.7.0 +│ │ │ │ │ │ │ │ │ │ ├── tap v1.0.1 +│ │ │ │ │ │ │ │ │ │ └── wyz v0.5.1 +│ │ │ │ │ │ │ │ │ │ └── tap v1.0.1 +│ │ │ │ │ │ │ │ │ ├── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ │ └── subtle v2.6.1 +│ │ │ │ │ │ │ │ ├── generic-array v0.14.9 (*) +│ │ │ │ │ │ │ │ ├── group v0.13.0 +│ │ │ │ │ │ │ │ │ ├── ff v0.13.1 (*) +│ │ │ │ │ │ │ │ │ ├── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ │ └── subtle v2.6.1 +│ │ │ │ │ │ │ │ ├── pkcs8 v0.10.2 +│ │ │ │ │ │ │ │ │ ├── der v0.7.10 (*) +│ │ │ │ │ │ │ │ │ └── spki v0.7.3 +│ │ │ │ │ │ │ │ │ └── der v0.7.10 (*) +│ │ │ │ │ │ │ │ ├── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ ├── sec1 v0.7.3 +│ │ │ │ │ │ │ │ │ ├── base16ct v0.2.0 +│ │ │ │ │ │ │ │ │ ├── der v0.7.10 (*) +│ │ │ │ │ │ │ │ │ ├── generic-array v0.14.9 (*) +│ │ │ │ │ │ │ │ │ ├── serdect v0.2.0 +│ │ │ │ │ │ │ │ │ │ ├── base16ct v0.2.0 +│ │ │ │ │ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ │ │ │ │ ├── subtle v2.6.1 +│ │ │ │ │ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ │ │ │ │ ├── serdect v0.2.0 (*) +│ │ │ │ │ │ │ │ ├── subtle v2.6.1 +│ │ │ │ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ │ │ │ ├── rfc6979 v0.4.0 +│ │ │ │ │ │ │ │ ├── hmac v0.12.1 +│ │ │ │ │ │ │ │ │ └── digest v0.10.7 (*) +│ │ │ │ │ │ │ │ └── subtle v2.6.1 +│ │ │ │ │ │ │ ├── serdect v0.2.0 (*) +│ │ │ │ │ │ │ ├── signature v2.2.0 +│ │ │ │ │ │ │ │ ├── digest v0.10.7 (*) +│ │ │ │ │ │ │ │ └── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ └── spki v0.7.3 (*) +│ │ │ │ │ │ ├── elliptic-curve v0.13.8 (*) +│ │ │ │ │ │ ├── serdect v0.2.0 (*) +│ │ │ │ │ │ └── sha2 v0.10.9 +│ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ ├── cpufeatures v0.2.17 +│ │ │ │ │ │ └── digest v0.10.7 (*) +│ │ │ │ │ ├── paste v1.0.15 (proc-macro) +│ │ │ │ │ ├── ruint v1.17.2 +│ │ │ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ │ │ ├── ruint-macro v1.2.1 (proc-macro) +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── rustc-hash v2.1.1 +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ └── sha3 v0.10.8 +│ │ │ │ │ ├── digest v0.10.7 (*) +│ │ │ │ │ └── keccak v0.1.6 +│ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ ├── crc v3.4.0 +│ │ │ │ │ └── crc-catalog v2.4.0 +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ └── thiserror v2.0.18 +│ │ │ │ └── thiserror-impl v2.0.18 (proc-macro) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ ├── alloy-eip2930 v0.2.3 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ └── serde v1.0.228 (*) +│ │ │ ├── alloy-eip7702 v0.6.3 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ ├── k256 v0.13.4 (*) +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ └── thiserror v2.0.18 (*) +│ │ │ ├── alloy-eip7928 v0.3.2 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ └── serde v1.0.228 (*) +│ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ ├── alloy-serde v1.7.3 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ └── serde_json v1.0.149 +│ │ │ │ ├── itoa v1.0.17 +│ │ │ │ ├── memchr v2.8.0 +│ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ └── zmij v1.0.21 +│ │ │ ├── auto_impl v1.3.0 (proc-macro) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ ├── derive_more v2.1.1 (*) +│ │ │ ├── either v1.15.0 +│ │ │ │ └── serde v1.0.228 (*) +│ │ │ ├── ethereum_ssz v0.9.1 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── ethereum_serde_utils v0.8.0 +│ │ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ │ ├── hex v0.4.3 +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ ├── serde_derive v1.0.228 (proc-macro) (*) +│ │ │ │ │ └── serde_json v1.0.149 (*) +│ │ │ │ ├── itertools v0.13.0 +│ │ │ │ │ └── either v1.15.0 (*) +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ ├── serde_derive v1.0.228 (proc-macro) (*) +│ │ │ │ ├── smallvec v1.15.1 +│ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ └── typenum v1.19.0 +│ │ │ ├── ethereum_ssz_derive v0.9.1 (proc-macro) +│ │ │ │ ├── darling v0.20.11 +│ │ │ │ │ ├── darling_core v0.20.11 +│ │ │ │ │ │ ├── fnv v1.0.7 +│ │ │ │ │ │ ├── ident_case v1.0.1 +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ ├── strsim v0.11.1 +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ └── darling_macro v0.20.11 (proc-macro) +│ │ │ │ │ ├── darling_core v0.20.11 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── serde_with v3.16.1 +│ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ └── serde_with_macros v3.16.1 (proc-macro) +│ │ │ │ ├── darling v0.21.3 +│ │ │ │ │ ├── darling_core v0.21.3 +│ │ │ │ │ │ ├── fnv v1.0.7 +│ │ │ │ │ │ ├── ident_case v1.0.1 +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ ├── serde v1.0.228 +│ │ │ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ │ │ └── serde_derive v1.0.228 (proc-macro) (*) +│ │ │ │ │ │ ├── strsim v0.11.1 +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ └── darling_macro v0.21.3 (proc-macro) +│ │ │ │ │ ├── darling_core v0.21.3 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ ├── sha2 v0.10.9 (*) +│ │ │ └── thiserror v2.0.18 (*) +│ │ ├── alloy-primitives v1.5.7 (*) +│ │ ├── alloy-rlp v0.3.13 (*) +│ │ ├── alloy-serde v1.7.3 (*) +│ │ ├── alloy-trie v0.9.4 +│ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ ├── arrayvec v0.7.6 (*) +│ │ │ ├── derive_more v2.1.1 (*) +│ │ │ ├── nybbles v0.4.8 +│ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ ├── ruint v1.17.2 (*) +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ └── smallvec v1.15.1 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── smallvec v1.15.1 (*) +│ │ │ ├── thiserror v2.0.18 (*) +│ │ │ └── tracing v0.1.44 +│ │ │ ├── pin-project-lite v0.2.16 +│ │ │ ├── tracing-attributes v0.1.31 (proc-macro) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ └── tracing-core v0.1.36 +│ │ │ └── once_cell v1.21.3 +│ │ ├── alloy-tx-macros v1.7.3 (proc-macro) +│ │ │ ├── darling v0.21.3 (*) +│ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ ├── quote v1.0.44 (*) +│ │ │ └── syn v2.0.117 (*) +│ │ ├── auto_impl v1.3.0 (proc-macro) (*) +│ │ ├── derive_more v2.1.1 (*) +│ │ ├── either v1.15.0 (*) +│ │ ├── k256 v0.13.4 (*) +│ │ ├── once_cell v1.21.3 +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_json v1.0.149 (*) +│ │ └── thiserror v2.0.18 (*) +│ ├── alloy-core v1.5.7 +│ │ ├── alloy-primitives v1.5.7 (*) +│ │ └── alloy-rlp v0.3.13 (*) +│ ├── alloy-eips v1.7.3 (*) +│ ├── alloy-rpc-types v1.7.3 +│ │ ├── alloy-primitives v1.5.7 (*) +│ │ ├── alloy-rpc-types-eth v1.7.3 +│ │ │ ├── alloy-consensus v1.7.3 (*) +│ │ │ ├── alloy-consensus-any v1.7.3 +│ │ │ │ ├── alloy-consensus v1.7.3 (*) +│ │ │ │ ├── alloy-eips v1.7.3 (*) +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ │ ├── alloy-serde v1.7.3 (*) +│ │ │ │ └── serde v1.0.228 (*) +│ │ │ ├── alloy-eips v1.7.3 (*) +│ │ │ ├── alloy-network-primitives v1.7.3 +│ │ │ │ ├── alloy-consensus v1.7.3 (*) +│ │ │ │ ├── alloy-eips v1.7.3 (*) +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ ├── alloy-serde v1.7.3 (*) +│ │ │ │ └── serde v1.0.228 (*) +│ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ ├── alloy-rlp v0.3.13 (*) +│ │ │ ├── alloy-serde v1.7.3 (*) +│ │ │ ├── alloy-sol-types v1.5.7 +│ │ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ │ └── alloy-sol-macro v1.5.7 (proc-macro) +│ │ │ │ ├── alloy-sol-macro-expander v1.5.7 +│ │ │ │ │ ├── alloy-sol-macro-input v1.5.7 +│ │ │ │ │ │ ├── const-hex v1.17.0 +│ │ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ │ └── cpufeatures v0.2.17 +│ │ │ │ │ │ ├── dunce v1.0.5 +│ │ │ │ │ │ ├── heck v0.5.0 +│ │ │ │ │ │ ├── macro-string v0.1.4 +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ ├── syn v2.0.117 (*) +│ │ │ │ │ │ └── syn-solidity v1.5.7 +│ │ │ │ │ │ ├── paste v1.0.15 (proc-macro) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ ├── const-hex v1.17.0 (*) +│ │ │ │ │ ├── heck v0.5.0 +│ │ │ │ │ ├── indexmap v2.13.0 +│ │ │ │ │ │ ├── equivalent v1.0.2 +│ │ │ │ │ │ └── hashbrown v0.16.1 +│ │ │ │ │ ├── proc-macro-error2 v2.0.1 +│ │ │ │ │ │ ├── proc-macro-error-attr2 v2.0.0 (proc-macro) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ └── quote v1.0.44 (*) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ ├── sha3 v0.10.8 +│ │ │ │ │ │ ├── digest v0.10.7 +│ │ │ │ │ │ │ ├── block-buffer v0.10.4 (*) +│ │ │ │ │ │ │ └── crypto-common v0.1.6 (*) +│ │ │ │ │ │ └── keccak v0.1.6 +│ │ │ │ │ ├── syn v2.0.117 (*) +│ │ │ │ │ └── syn-solidity v1.5.7 (*) +│ │ │ │ ├── alloy-sol-macro-input v1.5.7 (*) +│ │ │ │ ├── proc-macro-error2 v2.0.1 (*) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ ├── itertools v0.14.0 +│ │ │ │ └── either v1.15.0 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── serde_json v1.0.149 (*) +│ │ │ └── thiserror v2.0.18 (*) +│ │ ├── alloy-serde v1.7.3 (*) +│ │ └── serde v1.0.228 (*) +│ └── alloy-serde v1.7.3 (*) +├── eyre v0.6.12 +│ ├── indenter v0.3.4 +│ └── once_cell v1.21.3 +├── helios-consensus-core v0.11.0 (https://github.com/a16z/helios?rev=582fda319ed1ecb5fb82c71f4fa755a32e01031a#582fda31) +│ ├── alloy v1.7.3 (*) +│ ├── alloy-rlp v0.3.13 (*) +│ ├── bls12_381 v0.8.0 +│ │ ├── digest v0.9.0 +│ │ │ └── generic-array v0.14.9 (*) +│ │ ├── ff v0.13.1 (*) +│ │ ├── group v0.13.0 (*) +│ │ ├── pairing v0.23.0 +│ │ │ └── group v0.13.0 (*) +│ │ ├── rand_core v0.6.4 (*) +│ │ └── subtle v2.6.1 +│ ├── ethereum_ssz v0.9.1 (*) +│ ├── ethereum_ssz_derive v0.9.1 (proc-macro) (*) +│ ├── eyre v0.6.12 (*) +│ ├── serde v1.0.228 (*) +│ ├── sha2 v0.9.9 +│ │ ├── block-buffer v0.9.0 +│ │ │ └── generic-array v0.14.9 (*) +│ │ ├── cfg-if v1.0.4 +│ │ ├── cpufeatures v0.2.17 +│ │ ├── digest v0.9.0 (*) +│ │ └── opaque-debug v0.3.1 +│ ├── ssz_types v0.11.0 +│ │ ├── ethereum_serde_utils v0.8.0 (*) +│ │ ├── ethereum_ssz v0.9.1 (*) +│ │ ├── itertools v0.13.0 (*) +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_derive v1.0.228 (proc-macro) (*) +│ │ ├── smallvec v1.15.1 (*) +│ │ ├── tree_hash v0.10.0 +│ │ │ ├── alloy-primitives v1.5.7 (*) +│ │ │ ├── ethereum_hashing v0.7.0 (https://github.com/ncitron/ethereum_hashing?rev=7ee70944ed4fabe301551da8c447e4f4ae5e6c35#7ee70944) +│ │ │ │ ├── cpufeatures v0.2.17 +│ │ │ │ └── sha2 v0.10.9 (*) +│ │ │ ├── ethereum_ssz v0.9.1 (*) +│ │ │ ├── smallvec v1.15.1 (*) +│ │ │ └── typenum v1.19.0 +│ │ └── typenum v1.19.0 +│ ├── superstruct v0.7.0 (proc-macro) +│ │ ├── darling v0.13.4 +│ │ │ ├── darling_core v0.13.4 +│ │ │ │ ├── fnv v1.0.7 +│ │ │ │ ├── ident_case v1.0.1 +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ ├── strsim v0.10.0 +│ │ │ │ └── syn v1.0.109 +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── unicode-ident v1.0.24 +│ │ │ └── darling_macro v0.13.4 (proc-macro) +│ │ │ ├── darling_core v0.13.4 (*) +│ │ │ ├── quote v1.0.44 (*) +│ │ │ └── syn v1.0.109 (*) +│ │ ├── itertools v0.10.5 +│ │ │ └── either v1.15.0 +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ ├── smallvec v1.15.1 +│ │ └── syn v1.0.109 (*) +│ ├── thiserror v1.0.69 +│ │ └── thiserror-impl v1.0.69 (proc-macro) +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ └── syn v2.0.117 (*) +│ ├── tracing v0.1.44 (*) +│ ├── tree_hash v0.10.0 (*) +│ ├── tree_hash_derive v0.10.0 (proc-macro) +│ │ ├── darling v0.20.11 (*) +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ └── syn v2.0.117 (*) +│ └── typenum v1.19.0 +├── hex v0.4.3 +├── revm v34.0.0 +│ ├── revm-bytecode v8.0.0 +│ │ ├── bitvec v1.0.1 (*) +│ │ └── revm-primitives v22.0.0 +│ │ ├── alloy-primitives v1.5.7 (*) +│ │ ├── num_enum v0.7.5 +│ │ │ ├── num_enum_derive v0.7.5 (proc-macro) +│ │ │ │ ├── proc-macro-crate v3.4.0 +│ │ │ │ │ └── toml_edit v0.23.10+spec-1.0.0 +│ │ │ │ │ ├── indexmap v2.13.0 (*) +│ │ │ │ │ ├── toml_datetime v0.7.5+spec-1.1.0 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── toml_parser v1.0.9+spec-1.1.0 +│ │ │ │ │ │ └── winnow v0.7.14 +│ │ │ │ │ └── winnow v0.7.14 +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ └── syn v2.0.117 (*) +│ │ │ └── rustversion v1.0.22 (proc-macro) +│ │ └── once_cell v1.21.3 +│ ├── revm-context v13.0.0 +│ │ ├── bitvec v1.0.1 (*) +│ │ ├── cfg-if v1.0.4 +│ │ ├── derive-where v1.6.0 (proc-macro) +│ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ ├── quote v1.0.44 (*) +│ │ │ └── syn v2.0.117 (*) +│ │ ├── revm-bytecode v8.0.0 (*) +│ │ ├── revm-context-interface v14.0.0 +│ │ │ ├── alloy-eip2930 v0.2.3 (*) +│ │ │ ├── alloy-eip7702 v0.6.3 (*) +│ │ │ ├── auto_impl v1.3.0 (proc-macro) (*) +│ │ │ ├── either v1.15.0 (*) +│ │ │ ├── revm-database-interface v9.0.0 +│ │ │ │ ├── auto_impl v1.3.0 (proc-macro) (*) +│ │ │ │ ├── either v1.15.0 (*) +│ │ │ │ ├── revm-primitives v22.0.0 (*) +│ │ │ │ ├── revm-state v9.0.0 +│ │ │ │ │ ├── alloy-eip7928 v0.3.2 (*) +│ │ │ │ │ ├── bitflags v2.11.0 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── revm-bytecode v8.0.0 (*) +│ │ │ │ │ └── revm-primitives v22.0.0 (*) +│ │ │ │ └── thiserror v2.0.18 (*) +│ │ │ ├── revm-primitives v22.0.0 (*) +│ │ │ └── revm-state v9.0.0 (*) +│ │ ├── revm-database-interface v9.0.0 (*) +│ │ ├── revm-primitives v22.0.0 (*) +│ │ └── revm-state v9.0.0 (*) +│ ├── revm-context-interface v14.0.0 (*) +│ ├── revm-database v10.0.0 +│ │ ├── revm-bytecode v8.0.0 (*) +│ │ ├── revm-database-interface v9.0.0 (*) +│ │ ├── revm-primitives v22.0.0 (*) +│ │ └── revm-state v9.0.0 (*) +│ ├── revm-database-interface v9.0.0 (*) +│ ├── revm-handler v15.0.0 +│ │ ├── auto_impl v1.3.0 (proc-macro) (*) +│ │ ├── derive-where v1.6.0 (proc-macro) (*) +│ │ ├── revm-bytecode v8.0.0 (*) +│ │ ├── revm-context v13.0.0 (*) +│ │ ├── revm-context-interface v14.0.0 (*) +│ │ ├── revm-database-interface v9.0.0 (*) +│ │ ├── revm-interpreter v32.0.0 +│ │ │ ├── revm-bytecode v8.0.0 (*) +│ │ │ ├── revm-context-interface v14.0.0 (*) +│ │ │ ├── revm-primitives v22.0.0 (*) +│ │ │ └── revm-state v9.0.0 (*) +│ │ ├── revm-precompile v32.0.0 +│ │ │ ├── ark-bls12-381 v0.5.0 +│ │ │ │ ├── ark-ec v0.5.0 +│ │ │ │ │ ├── ahash v0.8.12 +│ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ ├── once_cell v1.21.3 +│ │ │ │ │ │ └── zerocopy v0.8.39 +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── version_check v0.9.5 +│ │ │ │ │ ├── ark-ff v0.5.0 +│ │ │ │ │ │ ├── ark-ff-asm v0.5.0 (proc-macro) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ ├── ark-ff-macros v0.5.0 (proc-macro) +│ │ │ │ │ │ │ ├── num-bigint v0.4.6 +│ │ │ │ │ │ │ │ ├── num-integer v0.1.46 +│ │ │ │ │ │ │ │ │ └── num-traits v0.2.19 +│ │ │ │ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ │ │ │ └── autocfg v1.5.0 +│ │ │ │ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ │ │ │ ├── num-traits v0.2.19 (*) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ ├── ark-serialize v0.5.0 +│ │ │ │ │ │ │ ├── ark-serialize-derive v0.5.0 (proc-macro) +│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ ├── ark-std v0.5.0 +│ │ │ │ │ │ │ │ ├── num-traits v0.2.19 +│ │ │ │ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ │ │ │ └── autocfg v1.5.0 +│ │ │ │ │ │ │ │ └── rand v0.8.5 +│ │ │ │ │ │ │ │ ├── rand_chacha v0.3.1 +│ │ │ │ │ │ │ │ │ ├── ppv-lite86 v0.2.21 +│ │ │ │ │ │ │ │ │ │ └── zerocopy v0.8.39 +│ │ │ │ │ │ │ │ │ └── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ └── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ ├── arrayvec v0.7.6 (*) +│ │ │ │ │ │ │ ├── digest v0.10.7 (*) +│ │ │ │ │ │ │ └── num-bigint v0.4.6 +│ │ │ │ │ │ │ ├── num-integer v0.1.46 +│ │ │ │ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ │ │ ├── ark-std v0.5.0 (*) +│ │ │ │ │ │ ├── arrayvec v0.7.6 (*) +│ │ │ │ │ │ ├── digest v0.10.7 (*) +│ │ │ │ │ │ ├── educe v0.6.0 (proc-macro) +│ │ │ │ │ │ │ ├── enum-ordinalize v4.3.2 +│ │ │ │ │ │ │ │ └── enum-ordinalize-derive v4.3.2 (proc-macro) +│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ ├── itertools v0.13.0 (*) +│ │ │ │ │ │ ├── num-bigint v0.4.6 (*) +│ │ │ │ │ │ ├── num-traits v0.2.19 (*) +│ │ │ │ │ │ ├── paste v1.0.15 (proc-macro) +│ │ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ │ ├── ark-poly v0.5.0 +│ │ │ │ │ │ ├── ahash v0.8.12 (*) +│ │ │ │ │ │ ├── ark-ff v0.5.0 (*) +│ │ │ │ │ │ ├── ark-serialize v0.5.0 (*) +│ │ │ │ │ │ ├── ark-std v0.5.0 (*) +│ │ │ │ │ │ ├── educe v0.6.0 (proc-macro) (*) +│ │ │ │ │ │ └── hashbrown v0.15.5 +│ │ │ │ │ │ └── allocator-api2 v0.2.21 +│ │ │ │ │ ├── ark-serialize v0.5.0 (*) +│ │ │ │ │ ├── ark-std v0.5.0 (*) +│ │ │ │ │ ├── educe v0.6.0 (proc-macro) (*) +│ │ │ │ │ ├── hashbrown v0.15.5 (*) +│ │ │ │ │ ├── itertools v0.13.0 (*) +│ │ │ │ │ ├── num-bigint v0.4.6 (*) +│ │ │ │ │ ├── num-integer v0.1.46 (*) +│ │ │ │ │ ├── num-traits v0.2.19 (*) +│ │ │ │ │ └── zeroize v1.8.2 (*) +│ │ │ │ ├── ark-ff v0.5.0 (*) +│ │ │ │ ├── ark-serialize v0.5.0 (*) +│ │ │ │ └── ark-std v0.5.0 (*) +│ │ │ ├── ark-bn254 v0.5.0 +│ │ │ │ ├── ark-ec v0.5.0 (*) +│ │ │ │ ├── ark-ff v0.5.0 (*) +│ │ │ │ └── ark-std v0.5.0 (*) +│ │ │ ├── ark-ec v0.5.0 (*) +│ │ │ ├── ark-ff v0.5.0 (*) +│ │ │ ├── ark-serialize v0.5.0 (*) +│ │ │ ├── arrayref v0.3.9 +│ │ │ ├── aurora-engine-modexp v1.2.0 +│ │ │ │ ├── hex v0.4.3 +│ │ │ │ └── num v0.4.3 +│ │ │ │ ├── num-bigint v0.4.6 (*) +│ │ │ │ ├── num-complex v0.4.6 +│ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ ├── num-integer v0.1.46 (*) +│ │ │ │ ├── num-iter v0.1.45 +│ │ │ │ │ ├── num-integer v0.1.46 (*) +│ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── autocfg v1.5.0 +│ │ │ │ ├── num-rational v0.4.2 +│ │ │ │ │ ├── num-bigint v0.4.6 (*) +│ │ │ │ │ ├── num-integer v0.1.46 (*) +│ │ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ │ └── num-traits v0.2.19 (*) +│ │ │ ├── cfg-if v1.0.4 +│ │ │ ├── k256 v0.13.4 (*) +│ │ │ ├── p256 v0.13.2 +│ │ │ │ ├── ecdsa v0.16.9 (*) +│ │ │ │ ├── elliptic-curve v0.13.8 (*) +│ │ │ │ ├── primeorder v0.13.6 +│ │ │ │ │ └── elliptic-curve v0.13.8 (*) +│ │ │ │ └── sha2 v0.10.9 (*) +│ │ │ ├── revm-primitives v22.0.0 (*) +│ │ │ ├── ripemd v0.1.3 +│ │ │ │ └── digest v0.10.7 (*) +│ │ │ └── sha2 v0.10.9 (*) +│ │ ├── revm-primitives v22.0.0 (*) +│ │ └── revm-state v9.0.0 (*) +│ ├── revm-inspector v15.0.0 +│ │ ├── auto_impl v1.3.0 (proc-macro) (*) +│ │ ├── either v1.15.0 (*) +│ │ ├── revm-context v13.0.0 (*) +│ │ ├── revm-database-interface v9.0.0 (*) +│ │ ├── revm-handler v15.0.0 (*) +│ │ ├── revm-interpreter v32.0.0 (*) +│ │ ├── revm-primitives v22.0.0 (*) +│ │ └── revm-state v9.0.0 (*) +│ ├── revm-interpreter v32.0.0 (*) +│ ├── revm-precompile v32.0.0 (*) +│ ├── revm-primitives v22.0.0 (*) +│ └── revm-state v9.0.0 (*) +├── serde v1.0.228 (*) +├── serde_json v1.0.149 (*) +├── tauri v2.10.2 +│ ├── anyhow v1.0.102 +│ ├── cookie v0.18.1 +│ │ └── time v0.3.47 +│ │ ├── deranged v0.5.8 +│ │ │ └── powerfmt v0.2.0 +│ │ ├── itoa v1.0.17 +│ │ ├── num-conv v0.2.0 +│ │ ├── powerfmt v0.2.0 +│ │ ├── time-core v0.1.8 +│ │ └── time-macros v0.2.27 (proc-macro) +│ │ ├── num-conv v0.2.0 +│ │ └── time-core v0.1.8 +│ │ [build-dependencies] +│ │ └── version_check v0.9.5 +│ ├── dirs v6.0.0 +│ │ └── dirs-sys v0.5.0 +│ │ ├── libc v0.2.182 +│ │ └── option-ext v0.2.0 +│ ├── dunce v1.0.5 +│ ├── getrandom v0.3.4 +│ │ ├── cfg-if v1.0.4 +│ │ └── libc v0.2.182 +│ ├── glob v0.3.3 +│ ├── gtk v0.18.2 +│ │ ├── atk v0.18.2 +│ │ │ ├── atk-sys v0.18.2 +│ │ │ │ ├── glib-sys v0.18.1 +│ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── system-deps v6.2.2 +│ │ │ │ │ ├── cfg-expr v0.15.8 +│ │ │ │ │ │ ├── smallvec v1.15.1 +│ │ │ │ │ │ └── target-lexicon v0.12.16 +│ │ │ │ │ ├── heck v0.5.0 +│ │ │ │ │ ├── pkg-config v0.3.32 +│ │ │ │ │ ├── toml v0.8.2 +│ │ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ │ ├── serde_spanned v0.6.9 +│ │ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ │ ├── toml_datetime v0.6.3 +│ │ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ │ └── toml_edit v0.20.2 +│ │ │ │ │ │ ├── indexmap v2.13.0 (*) +│ │ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ │ ├── serde_spanned v0.6.9 (*) +│ │ │ │ │ │ ├── toml_datetime v0.6.3 (*) +│ │ │ │ │ │ └── winnow v0.5.40 +│ │ │ │ │ └── version-compare v0.2.1 +│ │ │ │ ├── gobject-sys v0.18.0 +│ │ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ │ └── libc v0.2.182 +│ │ │ │ [build-dependencies] +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ ├── glib v0.18.5 +│ │ │ │ ├── bitflags v2.11.0 (*) +│ │ │ │ ├── futures-channel v0.3.32 +│ │ │ │ │ └── futures-core v0.3.32 +│ │ │ │ ├── futures-core v0.3.32 +│ │ │ │ ├── futures-executor v0.3.32 +│ │ │ │ │ ├── futures-core v0.3.32 +│ │ │ │ │ ├── futures-task v0.3.32 +│ │ │ │ │ └── futures-util v0.3.32 +│ │ │ │ │ ├── futures-core v0.3.32 +│ │ │ │ │ ├── futures-macro v0.3.32 (proc-macro) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ ├── futures-task v0.3.32 +│ │ │ │ │ ├── pin-project-lite v0.2.16 +│ │ │ │ │ └── slab v0.4.12 +│ │ │ │ ├── futures-task v0.3.32 +│ │ │ │ ├── futures-util v0.3.32 (*) +│ │ │ │ ├── gio-sys v0.18.1 +│ │ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ │ ├── glib-macros v0.18.5 (proc-macro) +│ │ │ │ │ ├── heck v0.4.1 +│ │ │ │ │ ├── proc-macro-crate v2.0.2 +│ │ │ │ │ │ ├── toml_datetime v0.6.3 (*) +│ │ │ │ │ │ └── toml_edit v0.20.2 (*) +│ │ │ │ │ ├── proc-macro-error v1.0.4 +│ │ │ │ │ │ ├── proc-macro-error-attr v1.0.4 (proc-macro) +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ └── quote v1.0.44 (*) +│ │ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ │ └── version_check v0.9.5 +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v1.0.109 (*) +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── version_check v0.9.5 +│ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ ├── libc v0.2.182 +│ │ │ │ ├── memchr v2.8.0 +│ │ │ │ ├── once_cell v1.21.3 +│ │ │ │ ├── smallvec v1.15.1 (*) +│ │ │ │ └── thiserror v1.0.69 (*) +│ │ │ └── libc v0.2.182 +│ │ ├── cairo-rs v0.18.5 +│ │ │ ├── bitflags v2.11.0 (*) +│ │ │ ├── cairo-sys-rs v0.18.2 +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ └── libc v0.2.182 +│ │ │ │ [build-dependencies] +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ ├── glib v0.18.5 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ ├── once_cell v1.21.3 +│ │ │ └── thiserror v1.0.69 (*) +│ │ ├── field-offset v0.3.6 +│ │ │ └── memoffset v0.9.1 +│ │ │ [build-dependencies] +│ │ │ └── autocfg v1.5.0 +│ │ │ [build-dependencies] +│ │ │ └── rustc_version v0.4.1 (*) +│ │ ├── futures-channel v0.3.32 (*) +│ │ ├── gdk v0.18.2 +│ │ │ ├── cairo-rs v0.18.5 (*) +│ │ │ ├── gdk-pixbuf v0.18.5 +│ │ │ │ ├── gdk-pixbuf-sys v0.18.0 +│ │ │ │ │ ├── gio-sys v0.18.1 (*) +│ │ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ │ ├── gio v0.18.4 +│ │ │ │ │ ├── futures-channel v0.3.32 (*) +│ │ │ │ │ ├── futures-core v0.3.32 +│ │ │ │ │ ├── futures-io v0.3.32 +│ │ │ │ │ ├── futures-util v0.3.32 (*) +│ │ │ │ │ ├── gio-sys v0.18.1 (*) +│ │ │ │ │ ├── glib v0.18.5 (*) +│ │ │ │ │ ├── libc v0.2.182 +│ │ │ │ │ ├── once_cell v1.21.3 +│ │ │ │ │ ├── pin-project-lite v0.2.16 +│ │ │ │ │ ├── smallvec v1.15.1 (*) +│ │ │ │ │ └── thiserror v1.0.69 (*) +│ │ │ │ ├── glib v0.18.5 (*) +│ │ │ │ ├── libc v0.2.182 +│ │ │ │ └── once_cell v1.21.3 +│ │ │ ├── gdk-sys v0.18.2 +│ │ │ │ ├── cairo-sys-rs v0.18.2 (*) +│ │ │ │ ├── gdk-pixbuf-sys v0.18.0 (*) +│ │ │ │ ├── gio-sys v0.18.1 (*) +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ ├── libc v0.2.182 +│ │ │ │ └── pango-sys v0.18.0 +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ └── libc v0.2.182 +│ │ │ │ [build-dependencies] +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ │ [build-dependencies] +│ │ │ │ ├── pkg-config v0.3.32 +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ ├── gio v0.18.4 (*) +│ │ │ ├── glib v0.18.5 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ └── pango v0.18.3 +│ │ │ ├── gio v0.18.4 (*) +│ │ │ ├── glib v0.18.5 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ ├── once_cell v1.21.3 +│ │ │ └── pango-sys v0.18.0 (*) +│ │ ├── gdk-pixbuf v0.18.5 (*) +│ │ ├── gio v0.18.4 (*) +│ │ ├── glib v0.18.5 (*) +│ │ ├── gtk-sys v0.18.2 +│ │ │ ├── atk-sys v0.18.2 (*) +│ │ │ ├── cairo-sys-rs v0.18.2 (*) +│ │ │ ├── gdk-pixbuf-sys v0.18.0 (*) +│ │ │ ├── gdk-sys v0.18.2 (*) +│ │ │ ├── gio-sys v0.18.1 (*) +│ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ └── pango-sys v0.18.0 (*) +│ │ │ [build-dependencies] +│ │ │ └── system-deps v6.2.2 (*) +│ │ ├── gtk3-macros v0.18.2 (proc-macro) +│ │ │ ├── proc-macro-crate v1.3.1 +│ │ │ │ ├── once_cell v1.21.3 +│ │ │ │ └── toml_edit v0.19.15 +│ │ │ │ ├── indexmap v2.13.0 (*) +│ │ │ │ ├── toml_datetime v0.6.3 (*) +│ │ │ │ └── winnow v0.5.40 +│ │ │ ├── proc-macro-error v1.0.4 (*) +│ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ ├── quote v1.0.44 (*) +│ │ │ └── syn v2.0.117 (*) +│ │ ├── libc v0.2.182 +│ │ └── pango v0.18.3 (*) +│ │ [build-dependencies] +│ │ └── pkg-config v0.3.32 +│ ├── heck v0.5.0 +│ ├── http v1.4.0 +│ │ ├── bytes v1.11.1 (*) +│ │ └── itoa v1.0.17 +│ ├── log v0.4.29 +│ ├── mime v0.3.17 +│ ├── muda v0.17.1 +│ │ ├── crossbeam-channel v0.5.15 +│ │ │ └── crossbeam-utils v0.8.21 +│ │ ├── dpi v0.1.2 +│ │ │ └── serde v1.0.228 (*) +│ │ ├── gtk v0.18.2 (*) +│ │ ├── keyboard-types v0.7.0 +│ │ │ ├── bitflags v2.11.0 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ └── unicode-segmentation v1.12.0 +│ │ ├── once_cell v1.21.3 +│ │ ├── serde v1.0.228 (*) +│ │ └── thiserror v2.0.18 (*) +│ ├── percent-encoding v2.3.2 +│ ├── raw-window-handle v0.6.2 +│ ├── serde v1.0.228 (*) +│ ├── serde_json v1.0.149 (*) +│ ├── serde_repr v0.1.20 (proc-macro) +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ └── syn v2.0.117 (*) +│ ├── serialize-to-javascript v0.1.2 +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_json v1.0.149 (*) +│ │ └── serialize-to-javascript-impl v0.1.2 (proc-macro) +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ └── syn v2.0.117 (*) +│ ├── tauri-macros v2.5.4 (proc-macro) +│ │ ├── heck v0.5.0 +│ │ ├── proc-macro2 v1.0.106 (*) +│ │ ├── quote v1.0.44 (*) +│ │ ├── syn v2.0.117 (*) +│ │ ├── tauri-codegen v2.5.4 +│ │ │ ├── base64 v0.22.1 +│ │ │ ├── brotli v8.0.2 +│ │ │ │ ├── alloc-no-stdlib v2.0.4 +│ │ │ │ ├── alloc-stdlib v0.2.2 +│ │ │ │ │ └── alloc-no-stdlib v2.0.4 +│ │ │ │ └── brotli-decompressor v5.0.0 +│ │ │ │ ├── alloc-no-stdlib v2.0.4 +│ │ │ │ └── alloc-stdlib v0.2.2 (*) +│ │ │ ├── ico v0.5.0 +│ │ │ │ ├── byteorder v1.5.0 +│ │ │ │ └── png v0.17.16 +│ │ │ │ ├── bitflags v1.3.2 +│ │ │ │ ├── crc32fast v1.5.0 +│ │ │ │ │ └── cfg-if v1.0.4 +│ │ │ │ ├── fdeflate v0.3.7 +│ │ │ │ │ └── simd-adler32 v0.3.8 +│ │ │ │ ├── flate2 v1.1.9 +│ │ │ │ │ ├── crc32fast v1.5.0 (*) +│ │ │ │ │ └── miniz_oxide v0.8.9 +│ │ │ │ │ ├── adler2 v2.0.1 +│ │ │ │ │ └── simd-adler32 v0.3.8 +│ │ │ │ └── miniz_oxide v0.8.9 (*) +│ │ │ ├── json-patch v3.0.1 +│ │ │ │ ├── jsonptr v0.6.3 +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ └── serde_json v1.0.149 +│ │ │ │ │ ├── itoa v1.0.17 +│ │ │ │ │ ├── memchr v2.8.0 +│ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ └── zmij v1.0.21 +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ ├── serde_json v1.0.149 (*) +│ │ │ │ └── thiserror v1.0.69 (*) +│ │ │ ├── png v0.17.16 (*) +│ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ ├── quote v1.0.44 (*) +│ │ │ ├── semver v1.0.27 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── serde_json v1.0.149 (*) +│ │ │ ├── sha2 v0.10.9 (*) +│ │ │ ├── syn v2.0.117 (*) +│ │ │ ├── tauri-utils v2.8.2 +│ │ │ │ ├── anyhow v1.0.102 +│ │ │ │ ├── brotli v8.0.2 (*) +│ │ │ │ ├── cargo_metadata v0.19.2 +│ │ │ │ │ ├── camino v1.2.2 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── cargo-platform v0.1.9 +│ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ ├── semver v1.0.27 (*) +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ ├── serde_json v1.0.149 (*) +│ │ │ │ │ └── thiserror v2.0.18 (*) +│ │ │ │ ├── ctor v0.2.9 (proc-macro) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── dunce v1.0.5 +│ │ │ │ ├── glob v0.3.3 +│ │ │ │ ├── html5ever v0.29.1 +│ │ │ │ │ ├── log v0.4.29 +│ │ │ │ │ ├── mac v0.1.1 +│ │ │ │ │ ├── markup5ever v0.14.1 +│ │ │ │ │ │ ├── log v0.4.29 +│ │ │ │ │ │ ├── phf v0.11.3 +│ │ │ │ │ │ │ ├── phf_macros v0.11.3 (proc-macro) +│ │ │ │ │ │ │ │ ├── phf_generator v0.11.3 +│ │ │ │ │ │ │ │ │ ├── phf_shared v0.11.3 +│ │ │ │ │ │ │ │ │ │ └── siphasher v1.0.2 +│ │ │ │ │ │ │ │ │ └── rand v0.8.5 +│ │ │ │ │ │ │ │ │ ├── libc v0.2.182 +│ │ │ │ │ │ │ │ │ ├── rand_chacha v0.3.1 +│ │ │ │ │ │ │ │ │ │ ├── ppv-lite86 v0.2.21 +│ │ │ │ │ │ │ │ │ │ │ └── zerocopy v0.8.39 +│ │ │ │ │ │ │ │ │ │ └── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ │ └── rand_core v0.6.4 (*) +│ │ │ │ │ │ │ │ ├── phf_shared v0.11.3 (*) +│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ └── phf_shared v0.11.3 (*) +│ │ │ │ │ │ ├── string_cache v0.8.9 +│ │ │ │ │ │ │ ├── new_debug_unreachable v1.0.6 +│ │ │ │ │ │ │ ├── parking_lot v0.12.5 +│ │ │ │ │ │ │ │ ├── lock_api v0.4.14 +│ │ │ │ │ │ │ │ │ └── scopeguard v1.2.0 +│ │ │ │ │ │ │ │ └── parking_lot_core v0.9.12 +│ │ │ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ │ │ ├── libc v0.2.182 +│ │ │ │ │ │ │ │ └── smallvec v1.15.1 +│ │ │ │ │ │ │ ├── phf_shared v0.11.3 (*) +│ │ │ │ │ │ │ ├── precomputed-hash v0.1.1 +│ │ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ │ └── tendril v0.4.3 +│ │ │ │ │ │ ├── futf v0.1.5 +│ │ │ │ │ │ │ ├── mac v0.1.1 +│ │ │ │ │ │ │ └── new_debug_unreachable v1.0.6 +│ │ │ │ │ │ ├── mac v0.1.1 +│ │ │ │ │ │ └── utf-8 v0.7.6 +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ ├── phf_codegen v0.11.3 +│ │ │ │ │ │ │ ├── phf_generator v0.11.3 (*) +│ │ │ │ │ │ │ └── phf_shared v0.11.3 (*) +│ │ │ │ │ │ └── string_cache_codegen v0.5.4 +│ │ │ │ │ │ ├── phf_generator v0.11.3 (*) +│ │ │ │ │ │ ├── phf_shared v0.11.3 (*) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ └── quote v1.0.44 (*) +│ │ │ │ │ └── match_token v0.1.0 (proc-macro) +│ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── http v1.4.0 (*) +│ │ │ │ ├── infer v0.19.0 +│ │ │ │ │ └── cfb v0.7.3 +│ │ │ │ │ ├── byteorder v1.5.0 +│ │ │ │ │ ├── fnv v1.0.7 +│ │ │ │ │ └── uuid v1.21.0 +│ │ │ │ │ ├── getrandom v0.4.1 +│ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ ├── json-patch v3.0.1 (*) +│ │ │ │ ├── kuchikiki v0.8.8-speedreader +│ │ │ │ │ ├── cssparser v0.29.6 +│ │ │ │ │ │ ├── cssparser-macros v0.6.1 (proc-macro) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ ├── dtoa-short v0.3.5 +│ │ │ │ │ │ │ └── dtoa v1.0.11 +│ │ │ │ │ │ ├── itoa v1.0.17 +│ │ │ │ │ │ ├── matches v0.1.10 +│ │ │ │ │ │ ├── phf v0.10.1 +│ │ │ │ │ │ │ ├── phf_macros v0.10.0 (proc-macro) +│ │ │ │ │ │ │ │ ├── phf_generator v0.10.0 +│ │ │ │ │ │ │ │ │ ├── phf_shared v0.10.0 +│ │ │ │ │ │ │ │ │ │ └── siphasher v0.3.11 +│ │ │ │ │ │ │ │ │ └── rand v0.8.5 (*) +│ │ │ │ │ │ │ │ ├── phf_shared v0.10.0 (*) +│ │ │ │ │ │ │ │ ├── proc-macro-hack v0.5.20+deprecated (proc-macro) +│ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ └── syn v1.0.109 (*) +│ │ │ │ │ │ │ ├── phf_shared v0.10.0 (*) +│ │ │ │ │ │ │ └── proc-macro-hack v0.5.20+deprecated (proc-macro) +│ │ │ │ │ │ └── smallvec v1.15.1 +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v1.0.109 (*) +│ │ │ │ │ ├── html5ever v0.29.1 (*) +│ │ │ │ │ ├── indexmap v2.13.0 (*) +│ │ │ │ │ └── selectors v0.24.0 +│ │ │ │ │ ├── bitflags v1.3.2 +│ │ │ │ │ ├── cssparser v0.29.6 (*) +│ │ │ │ │ ├── derive_more v0.99.20 (proc-macro) +│ │ │ │ │ │ ├── convert_case v0.4.0 +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── rustc_version v0.4.1 (*) +│ │ │ │ │ ├── fxhash v0.2.1 +│ │ │ │ │ │ └── byteorder v1.5.0 +│ │ │ │ │ ├── log v0.4.29 +│ │ │ │ │ ├── phf v0.8.0 +│ │ │ │ │ │ └── phf_shared v0.8.0 +│ │ │ │ │ │ └── siphasher v0.3.11 +│ │ │ │ │ ├── precomputed-hash v0.1.1 +│ │ │ │ │ ├── servo_arc v0.2.0 +│ │ │ │ │ │ ├── nodrop v0.1.14 +│ │ │ │ │ │ └── stable_deref_trait v1.2.1 +│ │ │ │ │ └── smallvec v1.15.1 +│ │ │ │ │ [build-dependencies] +│ │ │ │ │ └── phf_codegen v0.8.0 +│ │ │ │ │ ├── phf_generator v0.8.0 +│ │ │ │ │ │ ├── phf_shared v0.8.0 (*) +│ │ │ │ │ │ └── rand v0.7.3 +│ │ │ │ │ │ ├── getrandom v0.1.16 +│ │ │ │ │ │ │ ├── cfg-if v1.0.4 +│ │ │ │ │ │ │ └── libc v0.2.182 +│ │ │ │ │ │ ├── libc v0.2.182 +│ │ │ │ │ │ ├── rand_chacha v0.2.2 +│ │ │ │ │ │ │ ├── ppv-lite86 v0.2.21 (*) +│ │ │ │ │ │ │ └── rand_core v0.5.1 +│ │ │ │ │ │ │ └── getrandom v0.1.16 (*) +│ │ │ │ │ │ ├── rand_core v0.5.1 (*) +│ │ │ │ │ │ └── rand_pcg v0.2.1 +│ │ │ │ │ │ └── rand_core v0.5.1 (*) +│ │ │ │ │ └── phf_shared v0.8.0 (*) +│ │ │ │ ├── log v0.4.29 +│ │ │ │ ├── memchr v2.8.0 +│ │ │ │ ├── phf v0.11.3 (*) +│ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ ├── regex v1.12.3 +│ │ │ │ │ ├── aho-corasick v1.1.4 +│ │ │ │ │ │ └── memchr v2.8.0 +│ │ │ │ │ ├── memchr v2.8.0 +│ │ │ │ │ ├── regex-automata v0.4.14 +│ │ │ │ │ │ ├── aho-corasick v1.1.4 (*) +│ │ │ │ │ │ ├── memchr v2.8.0 +│ │ │ │ │ │ └── regex-syntax v0.8.9 +│ │ │ │ │ └── regex-syntax v0.8.9 +│ │ │ │ ├── schemars v0.8.22 +│ │ │ │ │ ├── dyn-clone v1.0.20 +│ │ │ │ │ ├── indexmap v1.9.3 +│ │ │ │ │ │ ├── hashbrown v0.12.3 +│ │ │ │ │ │ └── serde v1.0.228 (*) +│ │ │ │ │ │ [build-dependencies] +│ │ │ │ │ │ └── autocfg v1.5.0 +│ │ │ │ │ ├── schemars_derive v0.8.22 (proc-macro) +│ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ ├── serde_derive_internals v0.29.1 +│ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ ├── serde_json v1.0.149 (*) +│ │ │ │ │ ├── url v2.5.8 +│ │ │ │ │ │ ├── form_urlencoded v1.2.2 +│ │ │ │ │ │ │ └── percent-encoding v2.3.2 +│ │ │ │ │ │ ├── idna v1.1.0 +│ │ │ │ │ │ │ ├── idna_adapter v1.2.1 +│ │ │ │ │ │ │ │ ├── icu_normalizer v2.1.1 +│ │ │ │ │ │ │ │ │ ├── icu_collections v2.1.1 +│ │ │ │ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) +│ │ │ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ │ │ │ ├── potential_utf v0.1.4 +│ │ │ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 +│ │ │ │ │ │ │ │ │ │ │ ├── yoke v0.8.1 +│ │ │ │ │ │ │ │ │ │ │ │ ├── stable_deref_trait v1.2.1 +│ │ │ │ │ │ │ │ │ │ │ │ ├── yoke-derive v0.8.1 (proc-macro) +│ │ │ │ │ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ │ │ │ │ │ ├── syn v2.0.117 (*) +│ │ │ │ │ │ │ │ │ │ │ │ │ └── synstructure v0.13.2 +│ │ │ │ │ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ │ │ │ │ │ └── zerofrom v0.1.6 +│ │ │ │ │ │ │ │ │ │ │ │ └── zerofrom-derive v0.1.6 (proc-macro) +│ │ │ │ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ │ │ │ │ ├── syn v2.0.117 (*) +│ │ │ │ │ │ │ │ │ │ │ │ └── synstructure v0.13.2 (*) +│ │ │ │ │ │ │ │ │ │ │ ├── zerofrom v0.1.6 (*) +│ │ │ │ │ │ │ │ │ │ │ └── zerovec-derive v0.11.2 (proc-macro) +│ │ │ │ │ │ │ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ │ │ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ │ │ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ │ │ │ │ │ │ ├── yoke v0.8.1 (*) +│ │ │ │ │ │ │ │ │ │ ├── zerofrom v0.1.6 (*) +│ │ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ │ │ ├── icu_normalizer_data v2.1.1 +│ │ │ │ │ │ │ │ │ ├── icu_provider v2.1.1 +│ │ │ │ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*) +│ │ │ │ │ │ │ │ │ │ ├── icu_locale_core v2.1.1 +│ │ │ │ │ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*) +│ │ │ │ │ │ │ │ │ │ │ ├── litemap v0.8.1 +│ │ │ │ │ │ │ │ │ │ │ ├── tinystr v0.8.2 +│ │ │ │ │ │ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*) +│ │ │ │ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ │ │ │ │ ├── writeable v0.6.2 +│ │ │ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ │ │ │ ├── writeable v0.6.2 +│ │ │ │ │ │ │ │ │ │ ├── yoke v0.8.1 (*) +│ │ │ │ │ │ │ │ │ │ ├── zerofrom v0.1.6 (*) +│ │ │ │ │ │ │ │ │ │ ├── zerotrie v0.2.3 +│ │ │ │ │ │ │ │ │ │ │ ├── displaydoc v0.2.5 (proc-macro) (*) +│ │ │ │ │ │ │ │ │ │ │ ├── yoke v0.8.1 (*) +│ │ │ │ │ │ │ │ │ │ │ └── zerofrom v0.1.6 (*) +│ │ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ │ │ ├── smallvec v1.15.1 +│ │ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ │ └── icu_properties v2.1.2 +│ │ │ │ │ │ │ │ ├── icu_collections v2.1.1 (*) +│ │ │ │ │ │ │ │ ├── icu_locale_core v2.1.1 (*) +│ │ │ │ │ │ │ │ ├── icu_properties_data v2.1.2 +│ │ │ │ │ │ │ │ ├── icu_provider v2.1.1 (*) +│ │ │ │ │ │ │ │ ├── zerotrie v0.2.3 (*) +│ │ │ │ │ │ │ │ └── zerovec v0.11.5 (*) +│ │ │ │ │ │ │ ├── smallvec v1.15.1 +│ │ │ │ │ │ │ └── utf8_iter v1.0.4 +│ │ │ │ │ │ ├── percent-encoding v2.3.2 +│ │ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ │ └── serde_derive v1.0.228 (proc-macro) (*) +│ │ │ │ │ └── uuid v1.21.0 (*) +│ │ │ │ ├── semver v1.0.27 (*) +│ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ ├── serde-untagged v0.1.9 +│ │ │ │ │ ├── erased-serde v0.4.9 +│ │ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ │ └── typeid v1.0.3 +│ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ └── typeid v1.0.3 +│ │ │ │ ├── serde_json v1.0.149 (*) +│ │ │ │ ├── serde_with v3.16.1 (*) +│ │ │ │ ├── thiserror v2.0.18 (*) +│ │ │ │ ├── toml v0.9.12+spec-1.1.0 +│ │ │ │ │ ├── serde_core v1.0.228 +│ │ │ │ │ ├── serde_spanned v1.0.4 +│ │ │ │ │ │ └── serde_core v1.0.228 +│ │ │ │ │ ├── toml_datetime v0.7.5+spec-1.1.0 (*) +│ │ │ │ │ ├── toml_parser v1.0.9+spec-1.1.0 (*) +│ │ │ │ │ ├── toml_writer v1.0.6+spec-1.1.0 +│ │ │ │ │ └── winnow v0.7.14 +│ │ │ │ ├── url v2.5.8 (*) +│ │ │ │ ├── urlpattern v0.3.0 +│ │ │ │ │ ├── regex v1.12.3 (*) +│ │ │ │ │ ├── serde v1.0.228 (*) +│ │ │ │ │ ├── unic-ucd-ident v0.9.0 +│ │ │ │ │ │ ├── unic-char-property v0.9.0 +│ │ │ │ │ │ │ └── unic-char-range v0.9.0 +│ │ │ │ │ │ ├── unic-char-range v0.9.0 +│ │ │ │ │ │ └── unic-ucd-version v0.9.0 +│ │ │ │ │ │ └── unic-common v0.9.0 +│ │ │ │ │ └── url v2.5.8 (*) +│ │ │ │ ├── uuid v1.21.0 (*) +│ │ │ │ └── walkdir v2.5.0 +│ │ │ │ └── same-file v1.0.6 +│ │ │ ├── thiserror v2.0.18 (*) +│ │ │ ├── url v2.5.8 (*) +│ │ │ ├── uuid v1.21.0 (*) +│ │ │ └── walkdir v2.5.0 (*) +│ │ └── tauri-utils v2.8.2 (*) +│ ├── tauri-runtime v2.10.0 +│ │ ├── cookie v0.18.1 (*) +│ │ ├── dpi v0.1.2 (*) +│ │ ├── gtk v0.18.2 (*) +│ │ ├── http v1.4.0 (*) +│ │ ├── raw-window-handle v0.6.2 +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_json v1.0.149 (*) +│ │ ├── tauri-utils v2.8.2 +│ │ │ ├── anyhow v1.0.102 +│ │ │ ├── brotli v8.0.2 (*) +│ │ │ ├── ctor v0.2.9 (proc-macro) (*) +│ │ │ ├── dunce v1.0.5 +│ │ │ ├── glob v0.3.3 +│ │ │ ├── http v1.4.0 (*) +│ │ │ ├── infer v0.19.0 (*) +│ │ │ ├── json-patch v3.0.1 (*) +│ │ │ ├── log v0.4.29 +│ │ │ ├── memchr v2.8.0 +│ │ │ ├── phf v0.11.3 (*) +│ │ │ ├── regex v1.12.3 (*) +│ │ │ ├── semver v1.0.27 +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── serde-untagged v0.1.9 (*) +│ │ │ ├── serde_json v1.0.149 (*) +│ │ │ ├── serde_with v3.16.1 (*) +│ │ │ ├── thiserror v2.0.18 (*) +│ │ │ ├── toml v0.9.12+spec-1.1.0 (*) +│ │ │ ├── url v2.5.8 (*) +│ │ │ ├── urlpattern v0.3.0 (*) +│ │ │ ├── uuid v1.21.0 +│ │ │ │ └── serde_core v1.0.228 +│ │ │ └── walkdir v2.5.0 (*) +│ │ ├── thiserror v2.0.18 (*) +│ │ ├── url v2.5.8 (*) +│ │ └── webkit2gtk v2.0.2 +│ │ ├── bitflags v1.3.2 +│ │ ├── cairo-rs v0.18.5 (*) +│ │ ├── gdk v0.18.2 (*) +│ │ ├── gdk-sys v0.18.2 (*) +│ │ ├── gio v0.18.4 (*) +│ │ ├── gio-sys v0.18.1 (*) +│ │ ├── glib v0.18.5 (*) +│ │ ├── glib-sys v0.18.1 (*) +│ │ ├── gobject-sys v0.18.0 (*) +│ │ ├── gtk v0.18.2 (*) +│ │ ├── gtk-sys v0.18.2 (*) +│ │ ├── javascriptcore-rs v1.1.2 +│ │ │ ├── bitflags v1.3.2 +│ │ │ ├── glib v0.18.5 (*) +│ │ │ └── javascriptcore-rs-sys v1.1.1 +│ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ └── libc v0.2.182 +│ │ │ [build-dependencies] +│ │ │ └── system-deps v6.2.2 (*) +│ │ ├── libc v0.2.182 +│ │ ├── once_cell v1.21.3 +│ │ ├── soup3 v0.5.0 +│ │ │ ├── futures-channel v0.3.32 (*) +│ │ │ ├── gio v0.18.4 (*) +│ │ │ ├── glib v0.18.5 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ └── soup3-sys v0.5.0 +│ │ │ ├── gio-sys v0.18.1 (*) +│ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ └── libc v0.2.182 +│ │ │ [build-dependencies] +│ │ │ └── system-deps v6.2.2 (*) +│ │ └── webkit2gtk-sys v2.0.2 +│ │ ├── bitflags v1.3.2 +│ │ ├── cairo-sys-rs v0.18.2 (*) +│ │ ├── gdk-sys v0.18.2 (*) +│ │ ├── gio-sys v0.18.1 (*) +│ │ ├── glib-sys v0.18.1 (*) +│ │ ├── gobject-sys v0.18.0 (*) +│ │ ├── gtk-sys v0.18.2 (*) +│ │ ├── javascriptcore-rs-sys v1.1.1 (*) +│ │ ├── libc v0.2.182 +│ │ └── soup3-sys v0.5.0 (*) +│ │ [build-dependencies] +│ │ ├── pkg-config v0.3.32 +│ │ └── system-deps v6.2.2 (*) +│ ├── tauri-runtime-wry v2.10.0 +│ │ ├── gtk v0.18.2 (*) +│ │ ├── http v1.4.0 (*) +│ │ ├── log v0.4.29 +│ │ ├── percent-encoding v2.3.2 +│ │ ├── raw-window-handle v0.6.2 +│ │ ├── tao v0.34.5 +│ │ │ ├── bitflags v2.11.0 (*) +│ │ │ ├── crossbeam-channel v0.5.15 (*) +│ │ │ ├── dlopen2 v0.8.2 +│ │ │ │ ├── dlopen2_derive v0.4.3 (proc-macro) +│ │ │ │ │ ├── proc-macro2 v1.0.106 (*) +│ │ │ │ │ ├── quote v1.0.44 (*) +│ │ │ │ │ └── syn v2.0.117 (*) +│ │ │ │ ├── libc v0.2.182 +│ │ │ │ └── once_cell v1.21.3 +│ │ │ ├── dpi v0.1.2 (*) +│ │ │ ├── gdkwayland-sys v0.18.2 +│ │ │ │ ├── gdk-sys v0.18.2 (*) +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ ├── gobject-sys v0.18.0 (*) +│ │ │ │ └── libc v0.2.182 +│ │ │ │ [build-dependencies] +│ │ │ │ ├── pkg-config v0.3.32 +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ ├── gdkx11-sys v0.18.2 +│ │ │ │ ├── gdk-sys v0.18.2 (*) +│ │ │ │ ├── glib-sys v0.18.1 (*) +│ │ │ │ ├── libc v0.2.182 +│ │ │ │ └── x11 v2.21.0 +│ │ │ │ └── libc v0.2.182 +│ │ │ │ [build-dependencies] +│ │ │ │ └── pkg-config v0.3.32 +│ │ │ │ [build-dependencies] +│ │ │ │ └── system-deps v6.2.2 (*) +│ │ │ ├── gtk v0.18.2 (*) +│ │ │ ├── lazy_static v1.5.0 +│ │ │ ├── libc v0.2.182 +│ │ │ ├── log v0.4.29 +│ │ │ ├── parking_lot v0.12.5 (*) +│ │ │ ├── raw-window-handle v0.6.2 +│ │ │ ├── url v2.5.8 (*) +│ │ │ └── x11-dl v2.21.0 +│ │ │ ├── libc v0.2.182 +│ │ │ └── once_cell v1.21.3 +│ │ │ [build-dependencies] +│ │ │ └── pkg-config v0.3.32 +│ │ ├── tauri-runtime v2.10.0 (*) +│ │ ├── tauri-utils v2.8.2 (*) +│ │ ├── url v2.5.8 (*) +│ │ ├── webkit2gtk v2.0.2 (*) +│ │ └── wry v0.54.2 +│ │ ├── cookie v0.18.1 (*) +│ │ ├── dirs v6.0.0 (*) +│ │ ├── dpi v0.1.2 (*) +│ │ ├── gdkx11 v0.18.2 +│ │ │ ├── gdk v0.18.2 (*) +│ │ │ ├── gdkx11-sys v0.18.2 (*) +│ │ │ ├── gio v0.18.4 (*) +│ │ │ ├── glib v0.18.5 (*) +│ │ │ ├── libc v0.2.182 +│ │ │ └── x11 v2.21.0 (*) +│ │ ├── gtk v0.18.2 (*) +│ │ ├── http v1.4.0 (*) +│ │ ├── javascriptcore-rs v1.1.2 (*) +│ │ ├── once_cell v1.21.3 +│ │ ├── percent-encoding v2.3.2 +│ │ ├── raw-window-handle v0.6.2 +│ │ ├── soup3 v0.5.0 (*) +│ │ ├── thiserror v2.0.18 (*) +│ │ ├── webkit2gtk v2.0.2 (*) +│ │ ├── webkit2gtk-sys v2.0.2 (*) +│ │ └── x11-dl v2.21.0 (*) +│ ├── tauri-utils v2.8.2 (*) +│ ├── thiserror v2.0.18 (*) +│ ├── tokio v1.49.0 +│ │ ├── bytes v1.11.1 (*) +│ │ └── pin-project-lite v0.2.16 +│ ├── url v2.5.8 (*) +│ └── webkit2gtk v2.0.2 (*) +│ [build-dependencies] +│ ├── glob v0.3.3 +│ ├── heck v0.5.0 +│ ├── tauri-build v2.5.5 +│ │ ├── anyhow v1.0.102 +│ │ ├── cargo_toml v0.22.3 +│ │ │ ├── serde v1.0.228 (*) +│ │ │ └── toml v0.9.12+spec-1.1.0 (*) +│ │ ├── dirs v6.0.0 (*) +│ │ ├── glob v0.3.3 +│ │ ├── heck v0.5.0 +│ │ ├── json-patch v3.0.1 (*) +│ │ ├── schemars v0.8.22 (*) +│ │ ├── semver v1.0.27 (*) +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_json v1.0.149 (*) +│ │ ├── tauri-utils v2.8.2 (*) +│ │ ├── tauri-winres v0.3.5 +│ │ │ ├── dunce v1.0.5 +│ │ │ ├── embed-resource v3.0.6 +│ │ │ │ ├── cc v1.2.56 +│ │ │ │ │ ├── find-msvc-tools v0.1.9 +│ │ │ │ │ └── shlex v1.3.0 +│ │ │ │ ├── memchr v2.8.0 +│ │ │ │ ├── rustc_version v0.4.1 (*) +│ │ │ │ └── toml v0.9.12+spec-1.1.0 (*) +│ │ │ └── toml v0.9.12+spec-1.1.0 (*) +│ │ ├── toml v0.9.12+spec-1.1.0 (*) +│ │ └── walkdir v2.5.0 (*) +│ └── tauri-utils v2.8.2 (*) +├── tauri-plugin-dialog v2.6.0 +│ ├── log v0.4.29 +│ ├── raw-window-handle v0.6.2 +│ ├── rfd v0.16.0 +│ │ ├── glib-sys v0.18.1 (*) +│ │ ├── gobject-sys v0.18.0 (*) +│ │ ├── gtk-sys v0.18.2 (*) +│ │ ├── log v0.4.29 +│ │ └── raw-window-handle v0.6.2 +│ ├── serde v1.0.228 (*) +│ ├── serde_json v1.0.149 (*) +│ ├── tauri v2.10.2 (*) +│ ├── tauri-plugin-fs v2.4.5 +│ │ ├── anyhow v1.0.102 +│ │ ├── dunce v1.0.5 +│ │ ├── glob v0.3.3 +│ │ ├── percent-encoding v2.3.2 +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_json v1.0.149 (*) +│ │ ├── serde_repr v0.1.20 (proc-macro) (*) +│ │ ├── tauri v2.10.2 (*) +│ │ ├── thiserror v2.0.18 (*) +│ │ └── url v2.5.8 (*) +│ │ [build-dependencies] +│ │ ├── schemars v0.8.22 (*) +│ │ ├── serde v1.0.228 (*) +│ │ ├── tauri-plugin v2.5.3 +│ │ │ ├── anyhow v1.0.102 +│ │ │ ├── glob v0.3.3 +│ │ │ ├── schemars v0.8.22 (*) +│ │ │ ├── serde v1.0.228 (*) +│ │ │ ├── serde_json v1.0.149 (*) +│ │ │ ├── tauri-utils v2.8.2 (*) +│ │ │ ├── toml v0.9.12+spec-1.1.0 (*) +│ │ │ └── walkdir v2.5.0 (*) +│ │ ├── tauri-utils v2.8.2 (*) +│ │ └── toml v0.9.12+spec-1.1.0 (*) +│ ├── thiserror v2.0.18 (*) +│ └── url v2.5.8 (*) +│ [build-dependencies] +│ └── tauri-plugin v2.5.3 (*) +├── tauri-plugin-fs v2.4.5 (*) +├── time v0.3.47 (*) +├── tree_hash v0.12.1 +│ ├── alloy-primitives v1.5.7 (*) +│ ├── ethereum_hashing v0.8.0 +│ │ ├── cpufeatures v0.2.17 +│ │ ├── ring v0.17.14 +│ │ │ ├── cfg-if v1.0.4 +│ │ │ ├── getrandom v0.2.17 (*) +│ │ │ └── untrusted v0.9.0 +│ │ │ [build-dependencies] +│ │ │ └── cc v1.2.56 (*) +│ │ └── sha2 v0.10.9 (*) +│ ├── ethereum_ssz v0.10.1 +│ │ ├── alloy-primitives v1.5.7 (*) +│ │ ├── ethereum_serde_utils v0.8.0 (*) +│ │ ├── itertools v0.14.0 (*) +│ │ ├── serde v1.0.228 (*) +│ │ ├── serde_derive v1.0.228 (proc-macro) (*) +│ │ ├── smallvec v1.15.1 (*) +│ │ └── typenum v1.19.0 +│ ├── smallvec v1.15.1 (*) +│ └── typenum v1.19.0 +├── typenum v1.19.0 +└── window-vibrancy v0.6.0 + └── raw-window-handle v0.6.2 +[build-dependencies] +└── tauri-build v2.5.5 (*) +``` diff --git a/scripts/audit/deps.sh b/scripts/audit/deps.sh new file mode 100755 index 00000000..2400fd24 --- /dev/null +++ b/scripts/audit/deps.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +OUT_DIR="$ROOT_DIR/docs/audit" +OUT_FILE="$OUT_DIR/dependency-footprint.md" +BASELINE_FILE="$OUT_DIR/dependency-footprint.baseline.md" +DIFF_FILE="$OUT_DIR/dependency-footprint.diff" +TMP_FILE="$(mktemp)" + +cleanup() { + rm -f "$TMP_FILE" +} +trap cleanup EXIT + +mkdir -p "$OUT_DIR" + +bun_lock_hash="missing" +if [[ -f "$ROOT_DIR/bun.lock" ]]; then + bun_lock_hash="$(sha256sum "$ROOT_DIR/bun.lock" | awk '{print $1}')" +fi + +cargo_lock_state="not-present" +if [[ -f "$ROOT_DIR/apps/desktop/src-tauri/Cargo.lock" ]]; then + cargo_lock_state="present" +fi + +{ + echo "# Dependency Footprint" + echo + echo "Generated by \`scripts/audit/deps.sh\`." + echo + echo "## Inputs" + echo + echo "- \`bun.lock\` SHA-256: \`$bun_lock_hash\`" + echo "- \`apps/desktop/src-tauri/Cargo.lock\`: \`$cargo_lock_state\`" + echo + echo "## JavaScript Dependency Tree (bun list --all)" + echo + echo '```text' + (cd "$ROOT_DIR" && bun list --all) + echo '```' + echo + echo "## Rust Dependency Tree (cargo tree for safelens-desktop)" + echo + echo '```text' + if [[ -f "$ROOT_DIR/apps/desktop/src-tauri/Cargo.lock" ]]; then + (cd "$ROOT_DIR" && cargo tree --manifest-path apps/desktop/src-tauri/Cargo.toml -p safelens-desktop --locked) + else + echo "NOTE: Cargo.lock is not committed for apps/desktop/src-tauri; using unlocked resolution snapshot." + (cd "$ROOT_DIR" && cargo tree --manifest-path apps/desktop/src-tauri/Cargo.toml -p safelens-desktop) + fi + echo '```' +} > "$TMP_FILE" + +mv "$TMP_FILE" "$OUT_FILE" + +if [[ -f "$BASELINE_FILE" ]]; then + if diff -u "$BASELINE_FILE" "$OUT_FILE" > "$DIFF_FILE"; then + echo "No dependency drift vs baseline: $BASELINE_FILE" + else + echo "Dependency drift detected. See: $DIFF_FILE" + fi +else + echo "No baseline found at $BASELINE_FILE." +fi + +echo "Wrote $OUT_FILE" From e939cea9e067290950671df1fd1f3fe7dab3240e Mon Sep 17 00:00:00 2001 From: "Thomas Marchand (agent)" Date: Thu, 26 Feb 2026 07:57:31 +0000 Subject: [PATCH 9/9] docs: explicitly mention local tx replay in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca681c08..0291aa50 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ SafeLens generates and verifies evidence packages for Gnosis Safe multisig transactions. Paste a Safe transaction URL into the [generator](https://safelens.lfg.rs/), download the `evidence.json`, then verify signatures and hashes offline using the desktop app or CLI. - **Generate** an `evidence.json` package from any Safe transaction URL -- **Verify** signatures, hashes, and enriched proofs locally with zero network access +- **Verify** signatures, hashes, enriched proofs, and local transaction replay checks with zero network access - **Clear signing** via built-in and ERC-7730 interpreters for human-readable transaction details - **Consensus checks** via embedded Helios verifier for beacon-mode consensus proofs