From 2aca464388c5efb0acf330ac9de332b0da925b89 Mon Sep 17 00:00:00 2001 From: CodeMaster4711 Date: Sun, 25 Jan 2026 20:14:13 +0100 Subject: [PATCH 01/10] fix: docker container on nix --- docker-compose.ci-test.yml | 50 ++++++++++++++++++ docker-compose.standalone.yml | 56 +++++++++++++++++++++ nixos-node/deploy.sh | 16 +----- nixos-node/modules/server-configuration.nix | 33 ++++++------ 4 files changed, 123 insertions(+), 32 deletions(-) create mode 100644 docker-compose.ci-test.yml create mode 100644 docker-compose.standalone.yml diff --git a/docker-compose.ci-test.yml b/docker-compose.ci-test.yml new file mode 100644 index 0000000..9f0ca0d --- /dev/null +++ b/docker-compose.ci-test.yml @@ -0,0 +1,50 @@ +version: '3.8' + +services: + postgres: + image: postgres:16-alpine + container_name: csf-postgres-ci + environment: + POSTGRES_USER: csf + POSTGRES_PASSWORD: csfpassword + POSTGRES_DB: financevault + volumes: + - postgres_ci_data:/var/lib/postgresql/data + ports: + - "5432:5432" + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -U csf -d financevault"] + interval: 10s + timeout: 5s + retries: 5 + + backend: + image: ghcr.io/cs-foundry/csf-core-backend:latest + container_name: csf-backend-ci + ports: + - "8000:8000" + environment: + - RUST_LOG=debug + - DATABASE_URL=postgres://csf:csfpassword@postgres:5432/financevault + - JWT_SECRET=test_secret_key_for_ci_validation + - FRONTEND_URL=http://localhost:3000 + depends_on: + postgres: + condition: service_healthy + restart: unless-stopped + + frontend: + image: ghcr.io/cs-foundry/csf-core-frontend:0.1.12 + container_name: csf-frontend-ci + ports: + - "3000:3000" + environment: + - PUBLIC_API_BASE_URL=http://localhost:8000 + - ORIGIN=http://localhost:3000 + depends_on: + - backend + restart: unless-stopped + +volumes: + postgres_ci_data: diff --git a/docker-compose.standalone.yml b/docker-compose.standalone.yml new file mode 100644 index 0000000..0f9789e --- /dev/null +++ b/docker-compose.standalone.yml @@ -0,0 +1,56 @@ +version: '3.8' + +services: + postgres: + image: postgres:16-alpine + container_name: csf-postgres + environment: + POSTGRES_USER: csf + POSTGRES_PASSWORD: csfpassword + POSTGRES_DB: financevault + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - "5432:5432" + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -U csf -d financevault"] + interval: 10s + timeout: 5s + retries: 5 + + backend: + build: + context: ./backend + dockerfile: Dockerfile + container_name: csf-backend + ports: + - "8000:8000" + environment: + - RUST_LOG=debug + - DATABASE_URL=postgres://csf:csfpassword@postgres:5432/financevault + - JWT_SECRET=supersecretkey_change_me_in_production + - FRONTEND_URL=http://localhost:3000 + depends_on: + postgres: + condition: service_healthy + restart: unless-stopped + + frontend: + build: + context: ./frontend + dockerfile: Dockerfile.prod + container_name: csf-frontend + ports: + - "3000:3000" + environment: + # URL to the backend for client-side requests (browser -> backend) + - PUBLIC_API_BASE_URL=http://localhost:8000 + # Internal URL if SSR needs to talk to backend (optional, handled by public usually if not specified) + - ORIGIN=http://localhost:3000 + depends_on: + - backend + restart: unless-stopped + +volumes: + postgres_data: diff --git a/nixos-node/deploy.sh b/nixos-node/deploy.sh index fa3e9e3..a84a64d 100755 --- a/nixos-node/deploy.sh +++ b/nixos-node/deploy.sh @@ -50,17 +50,5 @@ echo "✅ Deployment complete!" echo "" echo "📝 Next steps:" echo " - Test Docker: ssh $TARGET_HOST 'docker --version'" -echo " - Run test script: ssh $TARGET_HOST 'sudo /root/test-docker.sh'" -echo " - Check nginx: curl http://192.168.1.36:8080" -nixos-version -echo "" -echo "Running containers:" -docker ps -EOF - -echo "" -echo "🎉 Deployment completed successfully!" -echo "" -echo "Test the deployment:" -echo " curl http://192.168.1.36:8080" -echo " ssh ${SERVER_HOST} ./test-docker.sh" +echo " - Run test script: ssh $TARGET_HOST 'sudo /root/test-csf-backend.sh'" +echo " - Check backend: curl http://192.168.1.36:8000/health" diff --git a/nixos-node/modules/server-configuration.nix b/nixos-node/modules/server-configuration.nix index ee4d785..89d1f58 100644 --- a/nixos-node/modules/server-configuration.nix +++ b/nixos-node/modules/server-configuration.nix @@ -44,6 +44,7 @@ 80 # HTTP 443 # HTTPS 8080 # Docker nginx test + 8000 # CSF-Core Backend ]; }; }; @@ -159,21 +160,23 @@ # Create docker-compose.yml for CSF-Core Backend cat > /etc/csf-core/docker-compose.yml <<'EOF' +version: '3.8' + services: postgres: image: postgres:16-alpine container_name: csf-postgres - ports: - - "5432:5432" environment: - - POSTGRES_USER=csf_user - - POSTGRES_PASSWORD=csf_password - - POSTGRES_DB=csf_core + POSTGRES_USER: csf + POSTGRES_PASSWORD: csfpassword + POSTGRES_DB: csf_core volumes: - postgres_data:/var/lib/postgresql/data + ports: + - "5432:5432" restart: unless-stopped healthcheck: - test: ["CMD-SHELL", "pg_isready -U csf_user -d csf_core"] + test: ["CMD-SHELL", "pg_isready -U csf -d csf_core"] interval: 10s timeout: 5s retries: 5 @@ -184,23 +187,17 @@ services: ports: - "8000:8000" environment: - - DATABASE_URL=postgres://csf_user:csf_password@postgres:5432/csf_core - - JWT_SECRET=changeme_generate_secure_secret - - RUST_LOG=info - restart: unless-stopped + - RUST_LOG=debug + - DATABASE_URL=postgres://csf:csfpassword@postgres:5432/csf_core + - JWT_SECRET=supersecretkey_change_me_in_production + - FRONTEND_URL=http://localhost:3000 depends_on: postgres: condition: service_healthy - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8000/health"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s + restart: unless-stopped volumes: postgres_data: - driver: local EOF # Create test script @@ -230,7 +227,7 @@ echo "Testing backend API:" curl -s http://localhost:8000/health || echo "Backend not responding" echo "" echo "Testing database connection:" -docker exec csf-postgres pg_isready -U csf_user -d csf_core || echo "Database not ready" +docker exec csf-postgres pg_isready -U csf -d csf_core || echo "Database not ready" echo "" echo "=== Test Complete ===" EOF From 42524951a5d53c7fe48de02abb7cec99d7ee0550 Mon Sep 17 00:00:00 2001 From: CodeMaster4711 Date: Tue, 27 Jan 2026 15:04:32 +0100 Subject: [PATCH 02/10] fix: securtity issue fix sha-1 to sha-256 --- .env.example | 7 +++++-- backend/src/auth/crypto.rs | 6 +++--- frontend/package-lock.json | 4 ++-- frontend/src/lib/services/auth.ts | 5 ++++- frontend/src/routes/signin/+page.server.ts | 5 ++++- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index 042ccd3..3492c0e 100644 --- a/.env.example +++ b/.env.example @@ -10,10 +10,13 @@ JWT_SECRET=changeme_generate_secure_secret_with_openssl_rand_hex_32 # Backend Configuration # ============================================ # Database connection string -DATABASE_URL=sqlite:/data/finance.db +# For development with docker-compose.dev.yml, use: +DATABASE_URL=postgres://csf_user:csf_password@postgres:5432/csf_core +# For production with SQLite, use: +# DATABASE_URL=sqlite:/data/finance.db # Rust logging level (trace, debug, info, warn, error) -RUST_LOG=info +RUST_LOG=debug # Frontend URL for CORS (must match the actual frontend URL) FRONTEND_URL=http://localhost:3000 diff --git a/backend/src/auth/crypto.rs b/backend/src/auth/crypto.rs index 3ab72f7..031dbea 100644 --- a/backend/src/auth/crypto.rs +++ b/backend/src/auth/crypto.rs @@ -57,13 +57,13 @@ impl RsaKeyPair { pub fn decrypt_password(encrypted_password: &str, private_key: &str) -> CryptoResult { use rsa::Oaep; - use sha1::Sha1; + use sha2::Sha256; let private_key = RsaPrivateKey::from_pkcs1_pem(private_key)?; let encrypted_bytes = base64::engine::general_purpose::STANDARD.decode(encrypted_password)?; - // Use SHA-1 to match node-forge's default RSA-OAEP implementation - let padding = Oaep::new::(); + // Use SHA-256 for RSA-OAEP padding + let padding = Oaep::new::(); let decrypted = private_key.decrypt(padding, &encrypted_bytes)?; String::from_utf8(decrypted).map_err(|_| CryptoError::InvalidEncryptedData) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 34653b6..c2f272b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "frontend", - "version": "0.0.8", + "version": "0.2.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "frontend", - "version": "0.0.8", + "version": "0.2.2", "dependencies": { "@icons-pack/svelte-simple-icons": "^6.5.0", "@tailwindcss/typography": "0.5.19", diff --git a/frontend/src/lib/services/auth.ts b/frontend/src/lib/services/auth.ts index 7703f38..71cf338 100644 --- a/frontend/src/lib/services/auth.ts +++ b/frontend/src/lib/services/auth.ts @@ -48,7 +48,10 @@ export class AuthService { static encryptPassword(password: string, publicKey: string): string { const publicKeyObj = forge.pki.publicKeyFromPem(publicKey); - const encrypted = publicKeyObj.encrypt(password, 'RSA-OAEP'); + // Use RSA-OAEP with SHA-256 for encryption + const encrypted = publicKeyObj.encrypt(password, 'RSA-OAEP', { + md: forge.md.sha256.create() + }); return forge.util.encode64(encrypted); } diff --git a/frontend/src/routes/signin/+page.server.ts b/frontend/src/routes/signin/+page.server.ts index 818efe5..739a004 100644 --- a/frontend/src/routes/signin/+page.server.ts +++ b/frontend/src/routes/signin/+page.server.ts @@ -31,7 +31,10 @@ export const actions = { // Import node-forge for server-side encryption const forge = await import('node-forge'); const publicKeyObj = forge.default.pki.publicKeyFromPem(public_key); - const encrypted = publicKeyObj.encrypt(password as string, 'RSA-OAEP'); + // Use RSA-OAEP with SHA-256 for encryption + const encrypted = publicKeyObj.encrypt(password as string, 'RSA-OAEP', { + md: forge.default.md.sha256.create() + }); const encryptedPassword = forge.default.util.encode64(encrypted); // Login request From 8d40d6aa329ed175a41e38dcbf4c6aae1c55bd86 Mon Sep 17 00:00:00 2001 From: CodeMaster4711 Date: Fri, 30 Jan 2026 21:09:56 +0100 Subject: [PATCH 03/10] fix: structure porject fix --- agent/Cargo.lock | 2732 ----------------- agent/Cargo.toml | 67 - agent/config.example.toml | 54 - agent/config.toml | 16 - agent/src/client.rs | 103 - agent/src/collector.rs | 148 - agent/src/config.rs | 168 - agent/src/connect/certs.rs | 217 -- agent/src/connect/connector.rs | 432 --- agent/src/connect/mod.rs | 5 - agent/src/main.rs | 229 -- agent/test-p2p.sh | 136 - crates/agent/Cargo.toml | 6 + crates/agent/src/main.rs | 3 + crates/cli/Cargo.toml | 6 + crates/cli/src/main.rs | 3 + crates/control-plane/Cargo.toml | 6 + crates/control-plane/src/main.rs | 3 + crates/entity/Cargo.toml | 6 + crates/entity/src/main.rs | 3 + crates/migration/Cargo.toml | 6 + crates/migration/src/main.rs | 3 + crates/shared/Cargo.toml | 6 + crates/shared/src/main.rs | 3 + csf-core.service | 55 - docker-compose.ci-test.yml | 50 - docker-compose.local-backend.yml | 47 - docker-compose.local.yml | 40 - docker-compose.registry.yml | 42 - docker-compose.standalone.yml | 56 - docker-entrypoint.sh | 64 - docs/.github/CICD.md | 194 -- docs/.github/WORKFLOW_VISUALIZATION.md | 154 - docs/.github/workflows/README.md | 82 - docs/README.md | 73 - .../architecture/ARCHITECTURE_AGENT_SYSTEM.md | 449 --- docs/architecture/DAEMON_ARCHITECTURE.md | 235 -- .../DOCKER_CONTAINER_INTEGRATION.md | 232 -- docs/deployment/BRANCH_INSTALLATION.md | 175 -- docs/deployment/DEPLOYMENT.md | 189 -- docs/deployment/DOCKER_INTEGRATION_PLAN.md | 507 --- docs/deployment/INSTALLATION.md | 424 --- docs/deployment/UNINSTALL.md | 197 -- docs/development/LOCAL_BACKEND_DEVELOPMENT.md | 130 - docs/development/LOCAL_DEVELOPMENT.md | 214 -- docs/development/agent/TESTING.md | 196 -- docs/features/AUTO_UPDATER.md | 151 - docs/features/BETA_UPDATES.md | 206 -- docs/frontend/README.md | 38 - docs/internal/CHANGELOG.md | 148 - docs/internal/COMMIT_MESSAGE.md | 116 - docs/internal/VERSION_MANAGEMENT.md | 103 - docs/internal/backend/migration/README.md | 41 - docs/troubleshooting/TROUBLESHOOTING.md | 261 -- install-daemon.sh | 108 - start.sh | 56 - 56 files changed, 54 insertions(+), 9340 deletions(-) delete mode 100644 agent/Cargo.lock delete mode 100644 agent/Cargo.toml delete mode 100644 agent/config.example.toml delete mode 100644 agent/config.toml delete mode 100644 agent/src/client.rs delete mode 100644 agent/src/collector.rs delete mode 100644 agent/src/config.rs delete mode 100644 agent/src/connect/certs.rs delete mode 100644 agent/src/connect/connector.rs delete mode 100644 agent/src/connect/mod.rs delete mode 100644 agent/src/main.rs delete mode 100755 agent/test-p2p.sh create mode 100644 crates/agent/Cargo.toml create mode 100644 crates/agent/src/main.rs create mode 100644 crates/cli/Cargo.toml create mode 100644 crates/cli/src/main.rs create mode 100644 crates/control-plane/Cargo.toml create mode 100644 crates/control-plane/src/main.rs create mode 100644 crates/entity/Cargo.toml create mode 100644 crates/entity/src/main.rs create mode 100644 crates/migration/Cargo.toml create mode 100644 crates/migration/src/main.rs create mode 100644 crates/shared/Cargo.toml create mode 100644 crates/shared/src/main.rs delete mode 100644 csf-core.service delete mode 100644 docker-compose.ci-test.yml delete mode 100644 docker-compose.local-backend.yml delete mode 100644 docker-compose.local.yml delete mode 100644 docker-compose.registry.yml delete mode 100644 docker-compose.standalone.yml delete mode 100644 docker-entrypoint.sh delete mode 100644 docs/.github/CICD.md delete mode 100644 docs/.github/WORKFLOW_VISUALIZATION.md delete mode 100644 docs/.github/workflows/README.md delete mode 100644 docs/README.md delete mode 100644 docs/architecture/ARCHITECTURE_AGENT_SYSTEM.md delete mode 100644 docs/architecture/DAEMON_ARCHITECTURE.md delete mode 100644 docs/architecture/DOCKER_CONTAINER_INTEGRATION.md delete mode 100644 docs/deployment/BRANCH_INSTALLATION.md delete mode 100644 docs/deployment/DEPLOYMENT.md delete mode 100644 docs/deployment/DOCKER_INTEGRATION_PLAN.md delete mode 100644 docs/deployment/INSTALLATION.md delete mode 100644 docs/deployment/UNINSTALL.md delete mode 100644 docs/development/LOCAL_BACKEND_DEVELOPMENT.md delete mode 100644 docs/development/LOCAL_DEVELOPMENT.md delete mode 100644 docs/development/agent/TESTING.md delete mode 100644 docs/features/AUTO_UPDATER.md delete mode 100644 docs/features/BETA_UPDATES.md delete mode 100644 docs/frontend/README.md delete mode 100644 docs/internal/CHANGELOG.md delete mode 100644 docs/internal/COMMIT_MESSAGE.md delete mode 100644 docs/internal/VERSION_MANAGEMENT.md delete mode 100644 docs/internal/backend/migration/README.md delete mode 100644 docs/troubleshooting/TROUBLESHOOTING.md delete mode 100755 install-daemon.sh delete mode 100644 start.sh diff --git a/agent/Cargo.lock b/agent/Cargo.lock deleted file mode 100644 index b4b1c2c..0000000 --- a/agent/Cargo.lock +++ /dev/null @@ -1,2732 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" - -[[package]] -name = "arraydeque" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" - -[[package]] -name = "asn1-rs" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" -dependencies = [ - "asn1-rs-derive", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror", - "time", -] - -[[package]] -name = "asn1-rs-derive" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "async-trait" -version = "0.1.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "aws-lc-rs" -version = "1.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e84ce723ab67259cfeb9877c6a639ee9eb7a27b28123abd71db7f0d5d0cc9d86" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a442ece363113bd4bd4c8b18977a7798dd4d3c3383f34fb61936960e8f4ad8" -dependencies = [ - "cc", - "cmake", - "dunce", - "fs_extra", -] - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "bitflags" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" -dependencies = [ - "serde_core", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bumpalo" -version = "3.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" - -[[package]] -name = "bytes" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" - -[[package]] -name = "cc" -version = "1.2.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" -dependencies = [ - "find-msvc-tools", - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "chrono" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "cmake" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" -dependencies = [ - "cc", -] - -[[package]] -name = "config" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68578f196d2a33ff61b27fae256c3164f65e36382648e30666dde05b8cc9dfdf" -dependencies = [ - "async-trait", - "convert_case", - "json5", - "nom", - "pathdiff", - "ron", - "rust-ini", - "serde", - "serde_json", - "toml", - "yaml-rust2", -] - -[[package]] -name = "const-random" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" -dependencies = [ - "const-random-macro", -] - -[[package]] -name = "const-random-macro" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" -dependencies = [ - "getrandom 0.2.16", - "once_cell", - "tiny-keccak", -] - -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "csf-agent" -version = "0.1.0" -dependencies = [ - "anyhow", - "bytes", - "chrono", - "config", - "hostname", - "http-body-util", - "hyper", - "hyper-util", - "rcgen", - "reqwest", - "rustls", - "rustls-pemfile", - "serde", - "serde_json", - "sysinfo", - "thiserror", - "time", - "tokio", - "tokio-rustls", - "tokio-util", - "toml", - "tracing", - "tracing-subscriber", - "uuid", - "webpki", -] - -[[package]] -name = "data-encoding" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" - -[[package]] -name = "der-parser" -version = "9.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" -dependencies = [ - "asn1-rs", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - -[[package]] -name = "deranged" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dlv-list" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" -dependencies = [ - "const-random", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys 0.61.2", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "find-msvc-tools" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasip2", -] - -[[package]] -name = "h2" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" - -[[package]] -name = "hashlink" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "hostname" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd" -dependencies = [ - "cfg-if", - "libc", - "windows-link", -] - -[[package]] -name = "http" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" -dependencies = [ - "bytes", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" -dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "pin-utils", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" -dependencies = [ - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http", - "http-body", - "hyper", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite", - "socket2", - "system-configuration", - "tokio", - "tower-layer", - "tower-service", - "tracing", - "windows-registry", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core 0.62.2", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_collections" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" -dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" - -[[package]] -name = "icu_properties" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" -dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" - -[[package]] -name = "icu_provider" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" -dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - -[[package]] -name = "idna" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "indexmap" -version = "2.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" -dependencies = [ - "equivalent", - "hashbrown 0.16.1", -] - -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "json5" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" -dependencies = [ - "pest", - "pest_derive", - "serde", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.178" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" - -[[package]] -name = "linux-raw-sys" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" - -[[package]] -name = "litemap" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "memchr" -version = "2.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "mio" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", -] - -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - -[[package]] -name = "nu-ansi-term" -version = "0.50.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "oid-registry" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" -dependencies = [ - "asn1-rs", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "openssl" -version = "0.10.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-src" -version = "300.5.4+3.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507b3792995dae9b0df8a1c1e3771e8418b7c2d9f0baeba32e6fe8b06c7cb72" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" -dependencies = [ - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "ordered-multimap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" -dependencies = [ - "dlv-list", - "hashbrown 0.14.5", -] - -[[package]] -name = "parking_lot" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-link", -] - -[[package]] -name = "pathdiff" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" - -[[package]] -name = "pem" -version = "3.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" -dependencies = [ - "base64 0.22.1", - "serde_core", -] - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "pest" -version = "2.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22" -dependencies = [ - "memchr", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" -dependencies = [ - "pest", - "sha2", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "potential_utf" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" -dependencies = [ - "zerovec", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "proc-macro2" -version = "1.0.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "rayon" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "rcgen" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" -dependencies = [ - "pem", - "ring", - "rustls-pki-types", - "time", - "x509-parser", - "yasna", -] - -[[package]] -name = "redox_syscall" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex-automata" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" - -[[package]] -name = "reqwest" -version = "0.12.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" -dependencies = [ - "base64 0.22.1", - "bytes", - "encoding_rs", - "futures-core", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "js-sys", - "log", - "mime", - "native-tls", - "percent-encoding", - "pin-project-lite", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-native-tls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.16", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "ron" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" -dependencies = [ - "base64 0.21.7", - "bitflags", - "serde", - "serde_derive", -] - -[[package]] -name = "rust-ini" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0698206bcb8882bf2a9ecb4c1e7785db57ff052297085a6efd4fe42302068a" -dependencies = [ - "cfg-if", - "ordered-multimap", -] - -[[package]] -name = "rusticata-macros" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" -dependencies = [ - "nom", -] - -[[package]] -name = "rustix" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustls" -version = "0.23.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" -dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" -dependencies = [ - "zeroize", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "schannel" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.145" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", - "serde_core", -] - -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "socket2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sysinfo" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c33cd241af0f2e9e3b5c32163b873b29956890b5342e6745b917ce9d490f4af" -dependencies = [ - "core-foundation-sys", - "libc", - "memchr", - "ntapi", - "rayon", - "windows", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tempfile" -version = "3.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" -dependencies = [ - "fastrand", - "getrandom 0.3.4", - "once_cell", - "rustix", - "windows-sys 0.61.2", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "time" -version = "0.3.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde_core", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" - -[[package]] -name = "time-macros" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinystr" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tokio" -version = "1.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" -dependencies = [ - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.61.2", -] - -[[package]] -name = "tokio-macros" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "toml_write", - "winnow", -] - -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - -[[package]] -name = "tower" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" -dependencies = [ - "bitflags", - "bytes", - "futures-util", - "http", - "http-body", - "iri-string", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex-automata", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" - -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - -[[package]] -name = "unicode-ident" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "uuid" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" -dependencies = [ - "getrandom 0.3.4", - "js-sys", - "serde_core", - "wasm-bindgen", -] - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasip2" -version = "1.0.1+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "web-sys" -version = "0.3.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" -dependencies = [ - "windows-core 0.57.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" -dependencies = [ - "windows-implement 0.57.0", - "windows-interface 0.57.0", - "windows-result 0.1.2", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement 0.60.2", - "windows-interface 0.59.3", - "windows-link", - "windows-result 0.4.1", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-registry" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" -dependencies = [ - "windows-link", - "windows-result 0.4.1", - "windows-strings", -] - -[[package]] -name = "windows-result" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - -[[package]] -name = "winnow" -version = "0.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" -dependencies = [ - "memchr", -] - -[[package]] -name = "wit-bindgen" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" - -[[package]] -name = "writeable" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" - -[[package]] -name = "x509-parser" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" -dependencies = [ - "asn1-rs", - "data-encoding", - "der-parser", - "lazy_static", - "nom", - "oid-registry", - "ring", - "rusticata-macros", - "thiserror", - "time", -] - -[[package]] -name = "yaml-rust2" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8902160c4e6f2fb145dbe9d6760a75e3c9522d8bf796ed7047c85919ac7115f8" -dependencies = [ - "arraydeque", - "encoding_rs", - "hashlink", -] - -[[package]] -name = "yasna" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" -dependencies = [ - "time", -] - -[[package]] -name = "yoke" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" -dependencies = [ - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.8.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] - -[[package]] -name = "zeroize" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" - -[[package]] -name = "zerotrie" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/agent/Cargo.toml b/agent/Cargo.toml deleted file mode 100644 index a36f207..0000000 --- a/agent/Cargo.toml +++ /dev/null @@ -1,67 +0,0 @@ -[package] -name = "csf-agent" -version = "0.1.0" -edition = "2021" - -[dependencies] -# Async runtime -tokio = { version = "1", features = ["full"] } - -# System information -sysinfo = "0.32" - -# Serialization -serde = { version = "1", features = ["derive"] } -serde_json = "1" - -# HTTP client for server communication -reqwest = { version = "0.12", features = ["json"] } - -# Configuration -config = "0.14" -toml = "0.8" - -# Logging -tracing = "0.1" -tracing-subscriber = { version = "0.3", features = ["env-filter"] } - -# Error handling -anyhow = "1" -thiserror = "1" - -# UUID -uuid = { version = "1", features = ["v4", "serde"] } - -# Time -chrono = { version = "0.4", features = ["serde"] } -time = { version = "0.3", features = ["formatting", "parsing"] } - -# Hostname -hostname = "0.4" - -# TLS/mTLS -rustls = { version = "0.23", features = ["ring"] } -tokio-rustls = "0.26" -rustls-pemfile = "2.0" -rcgen = { version = "0.13", features = ["x509-parser"] } -webpki = "0.22" - -# Async HTTP server -hyper = { version = "1", features = ["full"] } -hyper-util = { version = "0.1", features = ["full"] } -http-body-util = "0.1" - -# Networking -tokio-util = { version = "0.7", features = ["codec"] } -bytes = "1" - -[features] -default = [] -vendored-openssl = ["reqwest/native-tls-vendored"] - -[profile.release] -opt-level = "z" # Optimize for size -lto = true # Link-time optimization -codegen-units = 1 # Better optimization -strip = true # Strip symbols - diff --git a/agent/config.example.toml b/agent/config.example.toml deleted file mode 100644 index 345ab4b..0000000 --- a/agent/config.example.toml +++ /dev/null @@ -1,54 +0,0 @@ -# CSF Agent Configuration -# This file is automatically generated on first run - -# Unique agent identifier (automatically generated) -agent_id = "00000000-0000-0000-0000-000000000000" - -# Agent name (defaults to hostname) -name = "my-agent" - -# Central server URL -server_url = "http://localhost:8000" - -# API key for authentication -api_key = "" - -# Metrics collection interval in seconds -collection_interval = 30 - -# Heartbeat interval in seconds -heartbeat_interval = 60 - -# Tags for this agent -tags = [] - -# P2P (Peer-to-Peer) Configuration -[p2p] -# Enable P2P connections between agents -enabled = false - -# Port to listen for incoming P2P connections -listen_port = 8443 - -# List of peer agents to connect to (format: "host:port") -# Example: peers = ["192.168.1.100:8443", "192.168.1.101:8443"] -peers = [] - -# Path to agent certificate -# Linux default: /etc/csf-agent/certs/agent.crt -# Windows default: C:\ProgramData\csf-agent\certs\agent.crt -cert_path = "" - -# Path to agent private key -# Linux default: /etc/csf-agent/certs/agent.key -# Windows default: C:\ProgramData\csf-agent\certs\agent.key -key_path = "" - -# Path to CA certificate -# Linux default: /etc/csf-agent/certs/ca.crt -# Windows default: C:\ProgramData\csf-agent\certs\ca.crt -ca_cert_path = "" - -# Automatically generate self-signed certificates if not found -# For production, set to false and provide your own certificates -auto_generate_certs = true diff --git a/agent/config.toml b/agent/config.toml deleted file mode 100644 index eb9d0cf..0000000 --- a/agent/config.toml +++ /dev/null @@ -1,16 +0,0 @@ -agent_id = "2e85616c-c24f-4d91-b024-cba384ff3887" -name = "Mac.localdomain" -server_url = "http://localhost:8000" -api_key = "" -collection_interval = 30 -heartbeat_interval = 60 -tags = [] - -[p2p] -enabled = false -listen_port = 8443 -peers = [] -cert_path = "/etc/csf-agent/certs/agent.crt" -key_path = "/etc/csf-agent/certs/agent.key" -ca_cert_path = "/etc/csf-agent/certs/ca.crt" -auto_generate_certs = true diff --git a/agent/src/client.rs b/agent/src/client.rs deleted file mode 100644 index d537d60..0000000 --- a/agent/src/client.rs +++ /dev/null @@ -1,103 +0,0 @@ -use crate::collector::SystemMetrics; -use crate::config::AgentConfig; -use anyhow::Result; -use chrono::{DateTime, Utc}; -use reqwest::Client; -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AgentRegistration { - pub agent_id: Uuid, - pub name: String, - pub hostname: String, - pub os_type: String, - pub os_version: String, - pub architecture: String, - pub agent_version: String, - pub tags: Vec, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct RegistrationResponse { - pub success: bool, - pub message: String, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Heartbeat { - pub agent_id: Uuid, - pub timestamp: DateTime, - pub status: String, -} - -#[derive(Clone)] -pub struct ServerClient { - client: Client, - server_url: String, - api_key: String, -} - -impl ServerClient { - pub fn new(config: &AgentConfig) -> Self { - Self { - client: Client::new(), - server_url: config.server_url.clone(), - api_key: config.api_key.clone(), - } - } - - pub async fn register(&self, registration: &AgentRegistration) -> Result { - let url = format!("{}/api/agents/register", self.server_url); - - let response = self - .client - .post(&url) - .header("X-API-Key", &self.api_key) - .json(registration) - .send() - .await?; - - if response.status().is_success() { - Ok(response.json().await?) - } else { - anyhow::bail!("Registration failed: {}", response.status()) - } - } - - pub async fn send_heartbeat(&self, heartbeat: &Heartbeat) -> Result<()> { - let url = format!("{}/api/agents/heartbeat", self.server_url); - - let response = self - .client - .post(&url) - .header("X-API-Key", &self.api_key) - .json(heartbeat) - .send() - .await?; - - if !response.status().is_success() { - anyhow::bail!("Heartbeat failed: {}", response.status()); - } - - Ok(()) - } - - pub async fn send_metrics(&self, metrics: &SystemMetrics) -> Result<()> { - let url = format!("{}/api/agents/metrics", self.server_url); - - let response = self - .client - .post(&url) - .header("X-API-Key", &self.api_key) - .json(metrics) - .send() - .await?; - - if !response.status().is_success() { - anyhow::bail!("Metrics upload failed: {}", response.status()); - } - - Ok(()) - } -} diff --git a/agent/src/collector.rs b/agent/src/collector.rs deleted file mode 100644 index 3a754ed..0000000 --- a/agent/src/collector.rs +++ /dev/null @@ -1,148 +0,0 @@ -use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; -use sysinfo::{Disks, Networks, System}; -use uuid::Uuid; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SystemMetrics { - pub agent_id: Uuid, - pub timestamp: DateTime, - - // CPU - pub cpu_model: String, - pub cpu_cores: u32, - pub cpu_threads: u32, - pub cpu_usage_percent: f32, - - // Memory - pub memory_total_bytes: u64, - pub memory_used_bytes: u64, - pub memory_usage_percent: f32, - - // Disk - pub disk_total_bytes: u64, - pub disk_used_bytes: u64, - pub disk_usage_percent: f32, - - // Network - pub network_rx_bytes: u64, - pub network_tx_bytes: u64, - - // System - pub os_name: String, - pub os_version: String, - pub kernel_version: String, - pub hostname: String, - pub uptime_seconds: u64, -} - -pub struct MetricsCollector { - system: System, - networks: Networks, - disks: Disks, -} - -impl MetricsCollector { - pub fn new() -> Self { - Self { - system: System::new_all(), - networks: Networks::new_with_refreshed_list(), - disks: Disks::new_with_refreshed_list(), - } - } - - pub fn collect(&mut self, agent_id: Uuid) -> SystemMetrics { - // Refresh all data - self.system.refresh_all(); - self.networks.refresh(); - self.disks.refresh(); - - // CPU info - let cpu_model = self - .system - .cpus() - .first() - .map(|cpu| cpu.brand().to_string()) - .unwrap_or_else(|| "Unknown".to_string()); - - let cpu_cores = self.system.physical_core_count().unwrap_or(0) as u32; - let cpu_threads = self.system.cpus().len() as u32; - - let cpu_usage_percent = if !self.system.cpus().is_empty() { - let total: f32 = self.system.cpus().iter().map(|cpu| cpu.cpu_usage()).sum(); - total / self.system.cpus().len() as f32 - } else { - 0.0 - }; - - // Memory - let memory_total_bytes = self.system.total_memory(); - let memory_used_bytes = self.system.used_memory(); - let memory_usage_percent = if memory_total_bytes > 0 { - (memory_used_bytes as f32 / memory_total_bytes as f32) * 100.0 - } else { - 0.0 - }; - - // Disk - let (disk_total_bytes, disk_used_bytes) = - self.disks.iter().fold((0u64, 0u64), |(total, used), disk| { - ( - total + disk.total_space(), - used + (disk.total_space() - disk.available_space()), - ) - }); - - let disk_usage_percent = if disk_total_bytes > 0 { - (disk_used_bytes as f32 / disk_total_bytes as f32) * 100.0 - } else { - 0.0 - }; - - // Network - let (network_rx_bytes, network_tx_bytes) = - self.networks - .iter() - .fold((0u64, 0u64), |(rx, tx), (_name, network)| { - ( - rx + network.total_received(), - tx + network.total_transmitted(), - ) - }); - - // System info - let hostname = System::host_name().unwrap_or_else(|| "unknown".to_string()); - let os_name = System::name().unwrap_or_else(|| "Unknown".to_string()); - let os_version = System::os_version().unwrap_or_else(|| "Unknown".to_string()); - let kernel_version = System::kernel_version().unwrap_or_else(|| "Unknown".to_string()); - let uptime_seconds = System::uptime(); - - SystemMetrics { - agent_id, - timestamp: Utc::now(), - cpu_model, - cpu_cores, - cpu_threads, - cpu_usage_percent, - memory_total_bytes, - memory_used_bytes, - memory_usage_percent, - disk_total_bytes, - disk_used_bytes, - disk_usage_percent, - network_rx_bytes, - network_tx_bytes, - os_name, - os_version, - kernel_version, - hostname, - uptime_seconds, - } - } -} - -impl Default for MetricsCollector { - fn default() -> Self { - Self::new() - } -} diff --git a/agent/src/config.rs b/agent/src/config.rs deleted file mode 100644 index a969039..0000000 --- a/agent/src/config.rs +++ /dev/null @@ -1,168 +0,0 @@ -use serde::{Deserialize, Serialize}; -use uuid::Uuid; - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AgentConfig { - /// Unique agent ID (generated on first run) - pub agent_id: Uuid, - - /// Name of this agent - pub name: String, - - /// URL of the central server - pub server_url: String, - - /// API key for authentication (optional if only P2P is used) - pub api_key: String, - - /// Skip backend connection if only P2P mode is needed - pub p2p_only_mode: bool, - - /// How often to collect metrics (seconds) - pub collection_interval: u64, - - /// How often to send heartbeat (seconds) - pub heartbeat_interval: u64, - - /// Tags for this agent - pub tags: Vec, - - /// P2P connection settings - pub p2p: P2PConfig, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct P2PConfig { - /// Enable P2P connections between agents - pub enabled: bool, - - /// Port to listen for P2P connections - pub listen_port: u16, - - /// List of peer agents to connect to (host:port) - pub peers: Vec, - - /// mTLS certificate path - pub cert_path: String, - - /// mTLS private key path - pub key_path: String, - - /// CA certificate path for verifying peers - pub ca_cert_path: String, - - /// Auto-generate self-signed certificates if not found - pub auto_generate_certs: bool, -} - -impl Default for P2PConfig { - fn default() -> Self { - Self { - enabled: false, - listen_port: 8443, - peers: vec![], - cert_path: Self::default_cert_path().to_string_lossy().to_string(), - key_path: Self::default_key_path().to_string_lossy().to_string(), - ca_cert_path: Self::default_ca_cert_path().to_string_lossy().to_string(), - auto_generate_certs: true, - } - } -} - -impl P2PConfig { - fn default_cert_path() -> std::path::PathBuf { - if cfg!(target_os = "windows") { - std::path::PathBuf::from("C:\\ProgramData\\csf-agent\\certs\\agent.crt") - } else { - std::path::PathBuf::from("/etc/csf-agent/certs/agent.crt") - } - } - - fn default_key_path() -> std::path::PathBuf { - if cfg!(target_os = "windows") { - std::path::PathBuf::from("C:\\ProgramData\\csf-agent\\certs\\agent.key") - } else { - std::path::PathBuf::from("/etc/csf-agent/certs/agent.key") - } - } - - fn default_ca_cert_path() -> std::path::PathBuf { - if cfg!(target_os = "windows") { - std::path::PathBuf::from("C:\\ProgramData\\csf-agent\\certs\\ca.crt") - } else { - std::path::PathBuf::from("/etc/csf-agent/certs/ca.crt") - } - } -} - -impl Default for AgentConfig { - fn default() -> Self { - Self { - agent_id: Uuid::new_v4(), - name: hostname::get() - .ok() - .and_then(|h| h.into_string().ok()) - .unwrap_or_else(|| "unknown".to_string()), - server_url: "http://localhost:8000".to_string(), - api_key: String::new(), - p2p_only_mode: false, - collection_interval: 30, - heartbeat_interval: 60, - tags: vec![], - p2p: P2PConfig::default(), - } - } -} - -impl AgentConfig { - pub fn load() -> anyhow::Result { - // Try to load from config file, otherwise use defaults - // Check local directory first (for testing), then system path - let local_config = std::path::PathBuf::from("config.toml"); - let system_config = Self::config_path(); - - let config_path = if local_config.exists() { - local_config - } else { - system_config - }; - - if config_path.exists() { - let content = std::fs::read_to_string(&config_path)?; - Ok(toml::from_str(&content)?) - } else { - Ok(Self::default()) - } - } - - pub fn save(&self) -> anyhow::Result<()> { - // Try local directory first (for testing), then system path - let local_config = std::path::PathBuf::from("config.toml"); - let system_config = Self::config_path(); - - // If we can write to local directory, use that - let config_path = if local_config.exists() || std::env::current_dir().is_ok() { - local_config - } else { - system_config - }; - - // Create parent directory if it doesn't exist - if let Some(parent) = config_path.parent() { - std::fs::create_dir_all(parent).ok(); - } - - let content = toml::to_string_pretty(self)?; - std::fs::write(&config_path, content)?; - - Ok(()) - } - - fn config_path() -> std::path::PathBuf { - if cfg!(target_os = "windows") { - std::path::PathBuf::from("C:\\ProgramData\\csf-agent\\config.toml") - } else { - std::path::PathBuf::from("/etc/csf-agent/config.toml") - } - } -} diff --git a/agent/src/connect/certs.rs b/agent/src/connect/certs.rs deleted file mode 100644 index aa4a78b..0000000 --- a/agent/src/connect/certs.rs +++ /dev/null @@ -1,217 +0,0 @@ -use anyhow::{Context, Result}; -use rcgen::{ - BasicConstraints, CertificateParams, DistinguishedName, DnType, IsCa, KeyPair, KeyUsagePurpose, -}; -use std::fs; -use std::path::Path; -use time::{Duration, OffsetDateTime}; - -/// Generates a self-signed CA certificate -pub fn generate_ca_cert(common_name: &str, output_dir: &Path) -> Result<()> { - let mut params = CertificateParams::default(); - params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained); - - let mut dn = DistinguishedName::new(); - dn.push(DnType::CommonName, common_name); - dn.push(DnType::OrganizationName, "CSF Agent Network"); - dn.push(DnType::CountryName, "US"); - params.distinguished_name = dn; - - // Set validity period (10 years) - params.not_before = OffsetDateTime::now_utc(); - params.not_after = OffsetDateTime::now_utc() + Duration::days(3650); - - // Key usage for CA - params.key_usages = vec![ - KeyUsagePurpose::DigitalSignature, - KeyUsagePurpose::KeyCertSign, - KeyUsagePurpose::CrlSign, - ]; - - let key_pair = KeyPair::generate()?; - let cert = params.self_signed(&key_pair)?; - - // Create output directory - fs::create_dir_all(output_dir).context("Failed to create certificate directory")?; - - // Save CA certificate - let ca_cert_path = output_dir.join("ca.crt"); - fs::write(&ca_cert_path, cert.pem()).context("Failed to write CA certificate")?; - - // Save CA private key - let ca_key_path = output_dir.join("ca.key"); - fs::write(&ca_key_path, key_pair.serialize_pem()).context("Failed to write CA private key")?; - - // Set restrictive permissions on private key (Unix only) - #[cfg(unix)] - { - use std::os::unix::fs::PermissionsExt; - let mut perms = fs::metadata(&ca_key_path)?.permissions(); - perms.set_mode(0o600); - fs::set_permissions(&ca_key_path, perms)?; - } - - tracing::info!("Generated CA certificate at {:?}", ca_cert_path); - Ok(()) -} - -/// Generates an agent certificate signed by the CA -pub fn generate_agent_cert( - agent_name: &str, - ca_cert_path: &Path, - ca_key_path: &Path, - output_dir: &Path, -) -> Result<()> { - // Load CA certificate and key - let ca_cert_pem = fs::read_to_string(ca_cert_path).context("Failed to read CA certificate")?; - let ca_key_pem = fs::read_to_string(ca_key_path).context("Failed to read CA private key")?; - - let ca_key_pair = KeyPair::from_pem(&ca_key_pem).context("Failed to parse CA private key")?; - let ca_cert_params = CertificateParams::from_ca_cert_pem(&ca_cert_pem) - .context("Failed to parse CA certificate")?; - let ca_cert = ca_cert_params.self_signed(&ca_key_pair)?; - - // Create agent certificate parameters - let mut params = CertificateParams::default(); - - let mut dn = DistinguishedName::new(); - dn.push(DnType::CommonName, agent_name); - dn.push(DnType::OrganizationName, "CSF Agent Network"); - params.distinguished_name = dn; - - // Set validity period (1 year) - params.not_before = OffsetDateTime::now_utc(); - params.not_after = OffsetDateTime::now_utc() + Duration::days(365); - - // Key usage for agent certificates - params.key_usages = vec![ - KeyUsagePurpose::DigitalSignature, - KeyUsagePurpose::KeyEncipherment, - ]; - - // Extended key usage for server and client auth - params.extended_key_usages = vec![ - rcgen::ExtendedKeyUsagePurpose::ServerAuth, - rcgen::ExtendedKeyUsagePurpose::ClientAuth, - ]; - - // Add SubjectAlternativeNames for localhost and common IPs - params.subject_alt_names = vec![ - rcgen::SanType::DnsName("localhost".try_into().unwrap()), - rcgen::SanType::IpAddress(std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1))), - rcgen::SanType::IpAddress(std::net::IpAddr::V6(std::net::Ipv6Addr::new( - 0, 0, 0, 0, 0, 0, 0, 1, - ))), - ]; - - // Generate agent key pair - let agent_key_pair = KeyPair::generate()?; - - // Sign agent certificate with CA - let agent_cert = params.signed_by(&agent_key_pair, &ca_cert, &ca_key_pair)?; - - // Create output directory - fs::create_dir_all(output_dir).context("Failed to create certificate directory")?; - - // Save agent certificate - let agent_cert_path = output_dir.join("agent.crt"); - fs::write(&agent_cert_path, agent_cert.pem()).context("Failed to write agent certificate")?; - - // Save agent private key - let agent_key_path = output_dir.join("agent.key"); - fs::write(&agent_key_path, agent_key_pair.serialize_pem()) - .context("Failed to write agent private key")?; - - // Set restrictive permissions on private key (Unix only) - #[cfg(unix)] - { - use std::os::unix::fs::PermissionsExt; - let mut perms = fs::metadata(&agent_key_path)?.permissions(); - perms.set_mode(0o600); - fs::set_permissions(&agent_key_path, perms)?; - } - - tracing::info!("Generated agent certificate at {:?}", agent_cert_path); - Ok(()) -} - -/// Ensures certificates exist, generates them if needed -pub fn ensure_certificates(agent_name: &str, cert_dir: &Path, auto_generate: bool) -> Result<()> { - let ca_cert_path = cert_dir.join("ca.crt"); - let ca_key_path = cert_dir.join("ca.key"); - let agent_cert_path = cert_dir.join("agent.crt"); - let agent_key_path = cert_dir.join("agent.key"); - - // Check if certificates already exist - let ca_exists = ca_cert_path.exists() && ca_key_path.exists(); - let agent_exists = agent_cert_path.exists() && agent_key_path.exists(); - - if ca_exists && agent_exists { - tracing::info!("Certificates already exist, skipping generation"); - return Ok(()); - } - - if !auto_generate { - anyhow::bail!( - "Certificates not found and auto-generation is disabled. \ - Please provide certificates at {:?}", - cert_dir - ); - } - - tracing::info!("Generating certificates..."); - - // Generate CA if it doesn't exist - if !ca_exists { - let ca_common_name = format!("CSF-Agent-CA-{}", uuid::Uuid::new_v4()); - generate_ca_cert(&ca_common_name, cert_dir)?; - } - - // Generate agent certificate if it doesn't exist - if !agent_exists { - generate_agent_cert(agent_name, &ca_cert_path, &ca_key_path, cert_dir)?; - } - - Ok(()) -} - -/// Loads certificates for mTLS -pub fn load_certs(path: &Path) -> Result>> { - let cert_file = - fs::File::open(path).context(format!("Failed to open certificate file: {:?}", path))?; - let mut reader = std::io::BufReader::new(cert_file); - - rustls_pemfile::certs(&mut reader) - .collect::, _>>() - .context("Failed to parse certificates") -} - -/// Loads private key -pub fn load_private_key(path: &Path) -> Result> { - let key_file = - fs::File::open(path).context(format!("Failed to open private key file: {:?}", path))?; - let mut reader = std::io::BufReader::new(key_file); - - // Try to read as PKCS8 first - if let Some(key) = rustls_pemfile::pkcs8_private_keys(&mut reader) - .next() - .transpose() - .context("Failed to parse PKCS8 private key")? - { - return Ok(rustls::pki_types::PrivateKeyDer::Pkcs8(key)); - } - - // Reset reader and try RSA - let key_file = fs::File::open(path)?; - let mut reader = std::io::BufReader::new(key_file); - - if let Some(key) = rustls_pemfile::rsa_private_keys(&mut reader) - .next() - .transpose() - .context("Failed to parse RSA private key")? - { - return Ok(rustls::pki_types::PrivateKeyDer::Pkcs1(key)); - } - - anyhow::bail!("No valid private key found in {:?}", path) -} diff --git a/agent/src/connect/connector.rs b/agent/src/connect/connector.rs deleted file mode 100644 index bb785b8..0000000 --- a/agent/src/connect/connector.rs +++ /dev/null @@ -1,432 +0,0 @@ -use anyhow::{Context, Result}; -use chrono::{DateTime, Utc}; -use rustls::pki_types::{CertificateDer, PrivateKeyDer, ServerName}; -use rustls::RootCertStore; -use serde::{Deserialize, Serialize}; -use std::net::SocketAddr; -use std::path::Path; -use std::sync::Arc; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use tokio::net::{TcpListener, TcpStream}; -use tokio_rustls::{TlsAcceptor, TlsConnector}; -use uuid::Uuid; - -use super::certs; - -/// Message types for P2P communication -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum P2PMessage { - /// Handshake message to establish connection - Handshake { - agent_id: Uuid, - agent_name: String, - timestamp: DateTime, - }, - /// Heartbeat to maintain connection - Heartbeat { - agent_id: Uuid, - timestamp: DateTime, - }, - /// Share metrics with peer - MetricsShare { - agent_id: Uuid, - timestamp: DateTime, - metrics: serde_json::Value, - }, - /// Request metrics from peer - MetricsRequest { - agent_id: Uuid, - timestamp: DateTime, - }, - /// Response to a request - Response { - success: bool, - message: String, - data: Option, - }, -} - -/// mTLS P2P Connector for agent-to-agent communication -#[derive(Clone)] -pub struct P2PConnector { - agent_id: Uuid, - agent_name: String, - listen_addr: SocketAddr, - tls_acceptor: TlsAcceptor, - tls_connector: TlsConnector, -} - -impl P2PConnector { - /// Creates a new P2P connector with mTLS configuration - pub fn new( - agent_id: Uuid, - agent_name: String, - listen_port: u16, - cert_path: &Path, - key_path: &Path, - ca_cert_path: &Path, - ) -> Result { - // Load certificates - let certs = certs::load_certs(cert_path).context("Failed to load agent certificate")?; - let key = certs::load_private_key(key_path).context("Failed to load agent private key")?; - let ca_certs = certs::load_certs(ca_cert_path).context("Failed to load CA certificate")?; - - // Build server config (for accepting connections) - let server_config = Self::build_server_config(certs.clone(), key.clone_key(), &ca_certs)?; - let tls_acceptor = TlsAcceptor::from(Arc::new(server_config)); - - // Build client config (for initiating connections) - let client_config = Self::build_client_config(certs, key, &ca_certs)?; - let tls_connector = TlsConnector::from(Arc::new(client_config)); - - let listen_addr = SocketAddr::from(([0, 0, 0, 0], listen_port)); - - Ok(Self { - agent_id, - agent_name, - listen_addr, - tls_acceptor, - tls_connector, - }) - } - - /// Build server TLS config for accepting connections - fn build_server_config( - certs: Vec>, - key: PrivateKeyDer<'static>, - ca_certs: &[CertificateDer<'static>], - ) -> Result { - // Create root cert store for client verification - let mut root_store = RootCertStore::empty(); - for cert in ca_certs { - root_store - .add(cert.clone()) - .context("Failed to add CA certificate to root store")?; - } - - // Create verifier that requires client certificates - let client_verifier = rustls::server::WebPkiClientVerifier::builder(Arc::new(root_store)) - .build() - .context("Failed to build client verifier")?; - - let config = rustls::ServerConfig::builder() - .with_client_cert_verifier(client_verifier) - .with_single_cert(certs, key) - .context("Failed to build server config")?; - - Ok(config) - } - - /// Build client TLS config for initiating connections - fn build_client_config( - certs: Vec>, - key: PrivateKeyDer<'static>, - ca_certs: &[CertificateDer<'static>], - ) -> Result { - // Create root cert store for server verification - let mut root_store = RootCertStore::empty(); - for cert in ca_certs { - root_store - .add(cert.clone()) - .context("Failed to add CA certificate to root store")?; - } - - let config = rustls::ClientConfig::builder() - .with_root_certificates(root_store) - .with_client_auth_cert(certs, key) - .context("Failed to build client config")?; - - Ok(config) - } - - /// Start listening for incoming P2P connections - pub async fn start_server(&self) -> Result<()> { - let listener = TcpListener::bind(self.listen_addr) - .await - .context(format!("Failed to bind to {}", self.listen_addr))?; - - tracing::info!("P2P server listening on {}", self.listen_addr); - - loop { - match listener.accept().await { - Ok((stream, peer_addr)) => { - tracing::info!("Accepted connection from {}", peer_addr); - let acceptor = self.tls_acceptor.clone(); - let agent_id = self.agent_id; - let agent_name = self.agent_name.clone(); - - tokio::spawn(async move { - if let Err(e) = Self::handle_connection( - stream, acceptor, agent_id, agent_name, peer_addr, - ) - .await - { - tracing::error!("Error handling connection from {}: {}", peer_addr, e); - } - }); - } - Err(e) => { - tracing::error!("Error accepting connection: {}", e); - } - } - } - } - - /// Handle an incoming connection - async fn handle_connection( - stream: TcpStream, - acceptor: TlsAcceptor, - agent_id: Uuid, - agent_name: String, - peer_addr: SocketAddr, - ) -> Result<()> { - // Perform TLS handshake - let mut tls_stream = match acceptor.accept(stream).await { - Ok(s) => s, - Err(e) => { - anyhow::bail!("TLS handshake failed: {:?}", e); - } - }; - - tracing::info!("TLS handshake completed with {}", peer_addr); - - // Send handshake message - let handshake = P2PMessage::Handshake { - agent_id, - agent_name: agent_name.clone(), - timestamp: Utc::now(), - }; - Self::send_message(&mut tls_stream, &handshake).await?; - - // Receive handshake response - let response = Self::receive_message(&mut tls_stream).await?; - match response { - P2PMessage::Handshake { - agent_id: peer_id, - agent_name: peer_name, - .. - } => { - tracing::info!("Connected to peer: {} ({})", peer_name, peer_id); - } - _ => { - anyhow::bail!("Expected handshake message, got: {:?}", response); - } - } - - // Keep connection alive and handle messages - loop { - match Self::receive_message(&mut tls_stream).await { - Ok(message) => { - tracing::debug!("Received message: {:?}", message); - - // Handle different message types - match message { - P2PMessage::Heartbeat { - agent_id: peer_id, .. - } => { - tracing::debug!("Heartbeat from {}", peer_id); - - // Send heartbeat response - let response = P2PMessage::Response { - success: true, - message: "Heartbeat received".to_string(), - data: None, - }; - Self::send_message(&mut tls_stream, &response).await?; - } - P2PMessage::MetricsRequest { - agent_id: peer_id, .. - } => { - tracing::debug!("Metrics request from {}", peer_id); - - // TODO: Get current metrics and send them - let response = P2PMessage::Response { - success: true, - message: "Metrics data".to_string(), - data: Some(serde_json::json!({"status": "ok"})), - }; - Self::send_message(&mut tls_stream, &response).await?; - } - P2PMessage::MetricsShare { - agent_id: peer_id, - metrics, - .. - } => { - tracing::info!("Received metrics from {}: {:?}", peer_id, metrics); - } - _ => { - tracing::warn!("Unhandled message type: {:?}", message); - } - } - } - Err(e) => { - tracing::info!("Connection closed: {}", e); - break; - } - } - } - - Ok(()) - } - - /// Connect to a peer agent - pub async fn connect_to_peer( - &self, - peer_addr: &str, - ) -> Result> { - // Parse address - let addr: SocketAddr = peer_addr - .parse() - .context(format!("Invalid peer address: {}", peer_addr))?; - - tracing::info!("Connecting to peer at {}", addr); - - // Connect to peer - let stream = TcpStream::connect(addr) - .await - .context(format!("Failed to connect to {}", addr))?; - - // Extract hostname for SNI - let hostname = addr.ip().to_string(); - let server_name = ServerName::try_from(hostname) - .context("Invalid hostname")? - .to_owned(); - - // Perform TLS handshake - let mut tls_stream = match self.tls_connector.connect(server_name, stream).await { - Ok(s) => s, - Err(e) => { - anyhow::bail!("TLS handshake failed: {:?}", e); - } - }; - - tracing::info!("TLS handshake completed with {}", addr); - - // Receive handshake from server - let handshake = Self::receive_message(&mut tls_stream).await?; - match handshake { - P2PMessage::Handshake { - agent_id: peer_id, - agent_name: peer_name, - .. - } => { - tracing::info!("Connected to peer: {} ({})", peer_name, peer_id); - } - _ => { - anyhow::bail!("Expected handshake message"); - } - } - - // Send our handshake - let handshake = P2PMessage::Handshake { - agent_id: self.agent_id, - agent_name: self.agent_name.clone(), - timestamp: Utc::now(), - }; - Self::send_message(&mut tls_stream, &handshake).await?; - - Ok(tls_stream) - } - - /// Send a message over any TLS stream - async fn send_message(stream: &mut S, message: &P2PMessage) -> Result<()> - where - S: AsyncReadExt + AsyncWriteExt + Unpin, - { - let json = serde_json::to_string(message)?; - let len = json.len() as u32; - - // Send length prefix (4 bytes) - stream.write_all(&len.to_be_bytes()).await?; - // Send JSON data - stream.write_all(json.as_bytes()).await?; - stream.flush().await?; - - Ok(()) - } - - /// Receive a message from any TLS stream - async fn receive_message(stream: &mut S) -> Result - where - S: AsyncReadExt + AsyncWriteExt + Unpin, - { - // Read length prefix (4 bytes) - let mut len_bytes = [0u8; 4]; - stream.read_exact(&mut len_bytes).await?; - let len = u32::from_be_bytes(len_bytes) as usize; - - // Read JSON data - let mut buffer = vec![0u8; len]; - stream.read_exact(&mut buffer).await?; - - let message: P2PMessage = serde_json::from_slice(&buffer)?; - Ok(message) - } - - /// Send a heartbeat to a peer - pub async fn send_heartbeat(&self, stream: &mut S) -> Result<()> - where - S: AsyncReadExt + AsyncWriteExt + Unpin, - { - let heartbeat = P2PMessage::Heartbeat { - agent_id: self.agent_id, - timestamp: Utc::now(), - }; - - Self::send_message(stream, &heartbeat).await?; - - // Wait for response - let response = Self::receive_message(stream).await?; - match response { - P2PMessage::Response { - success, message, .. - } => { - if success { - tracing::debug!("Heartbeat acknowledged: {}", message); - } else { - anyhow::bail!("Heartbeat failed: {}", message); - } - } - _ => { - anyhow::bail!("Unexpected response to heartbeat"); - } - } - - Ok(()) - } - - /// Request metrics from a peer - #[allow(dead_code)] - pub async fn request_metrics(&self, stream: &mut S) -> Result - where - S: AsyncReadExt + AsyncWriteExt + Unpin, - { - let request = P2PMessage::MetricsRequest { - agent_id: self.agent_id, - timestamp: Utc::now(), - }; - - Self::send_message(stream, &request).await?; - - // Wait for response - let response = Self::receive_message(stream).await?; - match response { - P2PMessage::Response { - success, - data, - message, - .. - } => { - if success { - Ok(data.unwrap_or(serde_json::json!({}))) - } else { - anyhow::bail!("Metrics request failed: {}", message); - } - } - _ => { - anyhow::bail!("Unexpected response to metrics request"); - } - } - } -} diff --git a/agent/src/connect/mod.rs b/agent/src/connect/mod.rs deleted file mode 100644 index b21e81b..0000000 --- a/agent/src/connect/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod certs; -pub mod connector; - -pub use certs::ensure_certificates; -pub use connector::P2PConnector; diff --git a/agent/src/main.rs b/agent/src/main.rs deleted file mode 100644 index 5aea219..0000000 --- a/agent/src/main.rs +++ /dev/null @@ -1,229 +0,0 @@ -mod client; -mod collector; -mod config; -mod connect; - -use anyhow::Result; -use chrono::Utc; -use client::{AgentRegistration, Heartbeat, ServerClient}; -use collector::MetricsCollector; -use config::AgentConfig; -use connect::{ensure_certificates, P2PConnector}; -use std::time::Duration; -use tracing::{error, info, warn}; - -#[tokio::main] -async fn main() -> Result<()> { - // Initialize rustls crypto provider - let _ = rustls::crypto::ring::default_provider().install_default(); - - // Initialize logging - tracing_subscriber::fmt() - .with_env_filter( - tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")), - ) - .init(); - - info!("🚀 CSF Agent starting..."); - - // Load or create configuration - let config = AgentConfig::load().unwrap_or_else(|e| { - warn!("Failed to load config: {}. Using defaults.", e); - AgentConfig::default() - }); - - // Save config if it's new - if config.api_key.is_empty() { - warn!("⚠️ No API key configured. Agent will not be able to connect to server."); - warn!(" Please configure the agent by editing: /etc/csf-agent/config.toml"); - config.save()?; - return Ok(()); - } - - config.save()?; - info!("📝 Configuration loaded"); - info!(" Agent ID: {}", config.agent_id); - info!(" Name: {}", config.name); - if !config.p2p_only_mode { - info!(" Server: {}", config.server_url); - } else { - info!(" Mode: P2P Only (no backend connection)"); - } - - // Initialize P2P if enabled - let p2p_connector = if config.p2p.enabled { - info!("🔐 P2P connections enabled"); - - // Get certificate directory - let cert_dir = if let Some(parent) = std::path::Path::new(&config.p2p.cert_path).parent() { - parent.to_path_buf() - } else { - std::path::PathBuf::from(if cfg!(target_os = "windows") { - "C:\\ProgramData\\csf-agent\\certs" - } else { - "/etc/csf-agent/certs" - }) - }; - - // Ensure certificates exist - match ensure_certificates(&config.name, &cert_dir, config.p2p.auto_generate_certs) { - Ok(_) => info!("✅ Certificates ready"), - Err(e) => { - error!("❌ Failed to setup certificates: {}", e); - return Err(e); - } - } - - // Create P2P connector - match P2PConnector::new( - config.agent_id, - config.name.clone(), - config.p2p.listen_port, - std::path::Path::new(&config.p2p.cert_path), - std::path::Path::new(&config.p2p.key_path), - std::path::Path::new(&config.p2p.ca_cert_path), - ) { - Ok(connector) => { - info!( - "✅ P2P connector initialized on port {}", - config.p2p.listen_port - ); - Some(connector) - } - Err(e) => { - error!("❌ Failed to create P2P connector: {}", e); - return Err(e); - } - } - } else { - info!("ℹ️ P2P connections disabled"); - None - }; - - // Start P2P server if enabled - if let Some(ref connector) = p2p_connector { - let connector_clone = connector.clone(); - tokio::spawn(async move { - if let Err(e) = connector_clone.start_server().await { - error!("❌ P2P server error: {}", e); - } - }); - - // Connect to configured peers - for peer in &config.p2p.peers { - let connector_clone = connector.clone(); - let peer_addr = peer.clone(); - tokio::spawn(async move { - info!("🔗 Connecting to peer: {}", peer_addr); - match connector_clone.connect_to_peer(&peer_addr).await { - Ok(mut stream) => { - info!("✅ Connected to peer: {}", peer_addr); - - // Keep connection alive with heartbeats - let mut interval = tokio::time::interval(Duration::from_secs(30)); - loop { - interval.tick().await; - - if let Err(e) = connector_clone.send_heartbeat(&mut stream).await { - error!( - "❌ Heartbeat to {} failed: {}. Reconnecting...", - peer_addr, e - ); - break; - } - } - } - Err(e) => { - error!("❌ Failed to connect to peer {}: {}", peer_addr, e); - } - } - }); - } - } - - // Initialize components - let client = ServerClient::new(&config); - let mut collector = MetricsCollector::new(); - - // Register with server (skip if P2P only mode) - if !config.p2p_only_mode { - info!("📡 Registering with server..."); - let registration = AgentRegistration { - agent_id: config.agent_id, - name: config.name.clone(), - hostname: hostname::get() - .ok() - .and_then(|h| h.into_string().ok()) - .unwrap_or_else(|| "unknown".to_string()), - os_type: std::env::consts::OS.to_string(), - os_version: sysinfo::System::os_version().unwrap_or_else(|| "Unknown".to_string()), - architecture: std::env::consts::ARCH.to_string(), - agent_version: env!("CARGO_PKG_VERSION").to_string(), - tags: config.tags.clone(), - }; - - match client.register(®istration).await { - Ok(response) => { - info!("✅ Registration successful: {}", response.message); - } - Err(e) => { - error!("❌ Registration failed: {}", e); - warn!(" Continuing anyway, will retry on next heartbeat..."); - } - } - - // Spawn heartbeat task - let heartbeat_client = client.clone(); - let heartbeat_agent_id = config.agent_id; - let heartbeat_interval = config.heartbeat_interval; - tokio::spawn(async move { - let mut interval = tokio::time::interval(Duration::from_secs(heartbeat_interval)); - loop { - interval.tick().await; - - let heartbeat = Heartbeat { - agent_id: heartbeat_agent_id, - timestamp: Utc::now(), - status: "online".to_string(), - }; - - if let Err(e) = heartbeat_client.send_heartbeat(&heartbeat).await { - error!("Failed to send heartbeat: {}", e); - } else { - info!("💓 Heartbeat sent"); - } - } - }); - } else { - info!("ℹ️ Backend connection disabled (P2P only mode)"); - } - - // Main metrics collection loop - info!("📊 Starting metrics collection..."); - let mut interval = tokio::time::interval(Duration::from_secs(config.collection_interval)); - - loop { - interval.tick().await; - - // Collect metrics - let metrics = collector.collect(config.agent_id); - - info!( - "📈 Metrics - CPU: {:.1}% | RAM: {:.1}% | Disk: {:.1}%", - metrics.cpu_usage_percent, metrics.memory_usage_percent, metrics.disk_usage_percent - ); - - // Send to server (skip if P2P only mode) - if !config.p2p_only_mode { - match client.send_metrics(&metrics).await { - Ok(_) => { - info!("✅ Metrics sent to server"); - } - Err(e) => { - error!("❌ Failed to send metrics: {}", e); - } - } - } - } -} diff --git a/agent/test-p2p.sh b/agent/test-p2p.sh deleted file mode 100755 index 7cf4b94..0000000 --- a/agent/test-p2p.sh +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/bash - -echo "🧪 P2P mTLS Test" -echo "=================" - -# Cleanup -echo "🧹 Cleanup old test files..." -rm -rf test-agent1 test-agent2 -mkdir -p test-agent1/certs test-agent2/certs - -# Build -echo "🔨 Building agent..." -cargo build --release -if [ $? -ne 0 ]; then - echo "❌ Build failed" - exit 1 -fi - -# Create configs -echo "📝 Creating configurations..." - -CURRENT_DIR=$(pwd) - -cat > test-agent1/config.toml << EOF -agent_id = "11111111-1111-1111-1111-111111111111" -name = "test-agent-1" -server_url = "http://localhost:8000" -api_key = "test-key" -p2p_only_mode = true -collection_interval = 30 -heartbeat_interval = 60 -tags = [] - -[p2p] -enabled = true -listen_port = 8443 -peers = ["127.0.0.1:8444"] -cert_path = "$CURRENT_DIR/test-agent1/certs/agent.crt" -key_path = "$CURRENT_DIR/test-agent1/certs/agent.key" -ca_cert_path = "$CURRENT_DIR/test-agent1/certs/ca.crt" -auto_generate_certs = true -EOF - -cat > test-agent2/config.toml << EOF -agent_id = "22222222-2222-2222-2222-222222222222" -name = "test-agent-2" -server_url = "http://localhost:8000" -api_key = "test-key" -p2p_only_mode = true -collection_interval = 30 -heartbeat_interval = 60 -tags = [] - -[p2p] -enabled = true -listen_port = 8444 -peers = ["127.0.0.1:8443"] -cert_path = "$CURRENT_DIR/test-agent2/certs/agent.crt" -key_path = "$CURRENT_DIR/test-agent2/certs/agent.key" -ca_cert_path = "$CURRENT_DIR/test-agent2/certs/ca.crt" -auto_generate_certs = true -EOF - -# Start Agent 1 -echo "🚀 Starting Agent 1 (port 8443)..." -cd test-agent1 -RUST_LOG=info ../target/release/csf-agent > agent.log 2>&1 & -AGENT1_PID=$! -cd .. -echo " PID: $AGENT1_PID" - -# Wait for Agent 1 to start and generate certs -echo "⏳ Waiting for Agent 1 to generate certificates..." -sleep 4 - -# Copy CA cert from Agent 1 to Agent 2 -if [ -f "test-agent1/certs/ca.crt" ]; then - echo "📋 Sharing CA certificate with Agent 2..." - cp test-agent1/certs/ca.crt test-agent2/certs/ - cp test-agent1/certs/ca.key test-agent2/certs/ - echo "✅ CA certificate shared" -else - echo "❌ CA cert not found at test-agent1/certs/ca.crt" - echo " Check Agent 1 log for errors" - tail -10 test-agent1/agent.log - exit 1 -fi - -# Start Agent 2 -echo "🚀 Starting Agent 2 (port 8444)..." -cd test-agent2 -RUST_LOG=info ../target/release/csf-agent > agent.log 2>&1 & -AGENT2_PID=$! -cd .. -echo " PID: $AGENT2_PID" - -# Wait for connection -echo "⏳ Waiting for connection (10 seconds)..." -sleep 10 - -# Check logs -echo "" -echo "📊 Agent 1 Log:" -echo "===============" -tail -25 test-agent1/agent.log - -echo "" -echo "📊 Agent 2 Log:" -echo "===============" -tail -25 test-agent2/agent.log - -echo "" -echo "🔍 Checking for successful P2P connection..." -if grep -q "Connected to peer" test-agent1/agent.log && grep -q "Connected to peer" test-agent2/agent.log; then - echo "✅ SUCCESS! Both agents connected via mTLS" -elif grep -q "P2P server listening" test-agent1/agent.log && grep -q "P2P server listening" test-agent2/agent.log; then - echo "⚠️ Servers running but connection pending. Check logs for details." -else - echo "❌ Connection not established" -fi - -echo "" -echo "📝 Process Info:" -echo " Agent 1 PID: $AGENT1_PID" -echo " Agent 2 PID: $AGENT2_PID" -echo "" -echo "🛑 To stop agents:" -echo " kill $AGENT1_PID $AGENT2_PID" -echo "" -echo "📖 To follow logs:" -echo " tail -f test-agent1/agent.log" -echo " tail -f test-agent2/agent.log" -echo "" -echo "🧹 To cleanup:" -echo " kill $AGENT1_PID $AGENT2_PID 2>/dev/null" -echo " rm -rf test-agent1 test-agent2" diff --git a/crates/agent/Cargo.toml b/crates/agent/Cargo.toml new file mode 100644 index 0000000..1da0f28 --- /dev/null +++ b/crates/agent/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "agent" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/crates/agent/src/main.rs b/crates/agent/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/crates/agent/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml new file mode 100644 index 0000000..16d2db2 --- /dev/null +++ b/crates/cli/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "cli" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/crates/cli/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/crates/control-plane/Cargo.toml b/crates/control-plane/Cargo.toml new file mode 100644 index 0000000..e4b6694 --- /dev/null +++ b/crates/control-plane/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "control-plane" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/crates/control-plane/src/main.rs b/crates/control-plane/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/crates/control-plane/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/crates/entity/Cargo.toml b/crates/entity/Cargo.toml new file mode 100644 index 0000000..9aa365a --- /dev/null +++ b/crates/entity/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "entity" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/crates/entity/src/main.rs b/crates/entity/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/crates/entity/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/crates/migration/Cargo.toml b/crates/migration/Cargo.toml new file mode 100644 index 0000000..1246214 --- /dev/null +++ b/crates/migration/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "migration" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/crates/migration/src/main.rs b/crates/migration/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/crates/migration/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/crates/shared/Cargo.toml b/crates/shared/Cargo.toml new file mode 100644 index 0000000..5e22169 --- /dev/null +++ b/crates/shared/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "shared" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/crates/shared/src/main.rs b/crates/shared/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/crates/shared/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/csf-core.service b/csf-core.service deleted file mode 100644 index 5c95a54..0000000 --- a/csf-core.service +++ /dev/null @@ -1,55 +0,0 @@ -[Unit] -Description=CSF Core Backend and Frontend Service -Documentation=https://github.com/CS-Foundry/CSF-Core -After=network.target postgresql.service -Wants=postgresql.service - -[Service] -Type=forking -User=csf-core -Group=csf-core -WorkingDirectory=/opt/csf-core - -# Load environment from config file (if exists) -EnvironmentFile=-/opt/csf-core/config.env - -# Default environment variables (can be overridden in config.env) -Environment="DATABASE_URL=postgres://csf_core:password@localhost/csf_core" -Environment="JWT_SECRET=change-this-in-production" -Environment="RUST_LOG=info" -Environment="NODE_ENV=production" -Environment="PORT=3000" -Environment="FRONTEND_URL=http://localhost:3000" -Environment="ORIGIN=http://localhost:8000" - -# Security settings -NoNewPrivileges=true -PrivateTmp=true -ProtectSystem=strict -ProtectHome=true -ReadWritePaths=/opt/csf-core -ReadWritePaths=/var/lib/csf-core -ReadWritePaths=/var/log/csf-core -SupplementaryGroups=docker - -# Startup: Use unified startup script -ExecStart=/opt/csf-core/start.sh - -# Process management -Restart=on-failure -RestartSec=10 -KillMode=mixed -KillSignal=SIGTERM -TimeoutStartSec=60 -TimeoutStopSec=30 - -# Resource limits -LimitNOFILE=65536 -LimitNPROC=4096 - -# Logging -StandardOutput=append:/var/log/csf-core/csf-core.log -StandardError=append:/var/log/csf-core/csf-core-error.log - -[Install] -WantedBy=multi-user.target diff --git a/docker-compose.ci-test.yml b/docker-compose.ci-test.yml deleted file mode 100644 index 9f0ca0d..0000000 --- a/docker-compose.ci-test.yml +++ /dev/null @@ -1,50 +0,0 @@ -version: '3.8' - -services: - postgres: - image: postgres:16-alpine - container_name: csf-postgres-ci - environment: - POSTGRES_USER: csf - POSTGRES_PASSWORD: csfpassword - POSTGRES_DB: financevault - volumes: - - postgres_ci_data:/var/lib/postgresql/data - ports: - - "5432:5432" - restart: unless-stopped - healthcheck: - test: ["CMD-SHELL", "pg_isready -U csf -d financevault"] - interval: 10s - timeout: 5s - retries: 5 - - backend: - image: ghcr.io/cs-foundry/csf-core-backend:latest - container_name: csf-backend-ci - ports: - - "8000:8000" - environment: - - RUST_LOG=debug - - DATABASE_URL=postgres://csf:csfpassword@postgres:5432/financevault - - JWT_SECRET=test_secret_key_for_ci_validation - - FRONTEND_URL=http://localhost:3000 - depends_on: - postgres: - condition: service_healthy - restart: unless-stopped - - frontend: - image: ghcr.io/cs-foundry/csf-core-frontend:0.1.12 - container_name: csf-frontend-ci - ports: - - "3000:3000" - environment: - - PUBLIC_API_BASE_URL=http://localhost:8000 - - ORIGIN=http://localhost:3000 - depends_on: - - backend - restart: unless-stopped - -volumes: - postgres_ci_data: diff --git a/docker-compose.local-backend.yml b/docker-compose.local-backend.yml deleted file mode 100644 index d2eb26a..0000000 --- a/docker-compose.local-backend.yml +++ /dev/null @@ -1,47 +0,0 @@ -version: '3.8' - -# Use this compose file when running the backend locally (outside Docker) -# This will only start the frontend and postgres containers -# Run: docker-compose -f docker-compose.local-backend.yml up -d - -services: - frontend-dev: - build: - context: ./frontend - dockerfile: Dockerfile.dev - ports: - - "3000:3000" - env_file: - - .env - volumes: - - ./frontend:/app - - /app/node_modules - environment: - - NODE_ENV=development - - JWT_SECRET=${JWT_SECRET} - # Point to host.docker.internal for backend running on host machine - - PUBLIC_API_BASE_URL=http://localhost:8000/api - command: sh -c "npm install && JWT_SECRET=${JWT_SECRET} npm run dev -- --host 0.0.0.0 --port 3000" - extra_hosts: - - "host.docker.internal:host-gateway" - depends_on: - - postgres - - postgres: - image: postgres:16-alpine - ports: - - "5432:5432" - environment: - - POSTGRES_USER=csf_user - - POSTGRES_PASSWORD=csf_password - - POSTGRES_DB=csf_core - volumes: - - postgres_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U csf_user -d csf_core"] - interval: 10s - timeout: 5s - retries: 5 - -volumes: - postgres_data: diff --git a/docker-compose.local.yml b/docker-compose.local.yml deleted file mode 100644 index bfc3280..0000000 --- a/docker-compose.local.yml +++ /dev/null @@ -1,40 +0,0 @@ -version: '3.8' - -services: - postgres: - image: postgres:16-alpine - container_name: csf-postgres-local - ports: - - "5432:5432" - environment: - - POSTGRES_USER=csf_user - - POSTGRES_PASSWORD=csf_password - - POSTGRES_DB=csf_core - volumes: - - postgres_data_local:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U csf_user -d csf_core"] - interval: 10s - timeout: 5s - retries: 5 - - frontend: - build: - context: ./frontend - dockerfile: Dockerfile.dev - container_name: csf-frontend-local - ports: - - "3000:3000" - env_file: - - .env - volumes: - - ./frontend:/app - - /app/node_modules - environment: - - NODE_ENV=development - - PUBLIC_API_BASE_URL=http://localhost:8000/api - command: sh -c "npm install && npm run dev -- --host 0.0.0.0 --port 3000" - restart: unless-stopped - -volumes: - postgres_data_local: diff --git a/docker-compose.registry.yml b/docker-compose.registry.yml deleted file mode 100644 index 1d86ce3..0000000 --- a/docker-compose.registry.yml +++ /dev/null @@ -1,42 +0,0 @@ -# Docker Compose configuration using GitHub Container Registry images -# This file uses the published Docker images from ghcr.io - -version: '3.8' - -services: - backend: - image: ghcr.io/cs-foundry/csf-core-backend:latest - container_name: csf-backend - ports: - - "8000:8000" - environment: - - DATABASE_URL=sqlite:/data/finance.db - - RUST_LOG=info - - JWT_SECRET=${JWT_SECRET:-changeme} - - FRONTEND_URL=http://frontend:80 - volumes: - - csf_data:/data - restart: unless-stopped - healthcheck: - test: ["CMD", "/app/backend", "--health-check"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - - frontend: - image: ghcr.io/cs-foundry/csf-core-frontend:latest - container_name: csf-frontend - ports: - - "3000:80" - restart: unless-stopped - depends_on: - - backend - -volumes: - csf_data: - driver: local - -networks: - default: - name: csf-network diff --git a/docker-compose.standalone.yml b/docker-compose.standalone.yml deleted file mode 100644 index 0f9789e..0000000 --- a/docker-compose.standalone.yml +++ /dev/null @@ -1,56 +0,0 @@ -version: '3.8' - -services: - postgres: - image: postgres:16-alpine - container_name: csf-postgres - environment: - POSTGRES_USER: csf - POSTGRES_PASSWORD: csfpassword - POSTGRES_DB: financevault - volumes: - - postgres_data:/var/lib/postgresql/data - ports: - - "5432:5432" - restart: unless-stopped - healthcheck: - test: ["CMD-SHELL", "pg_isready -U csf -d financevault"] - interval: 10s - timeout: 5s - retries: 5 - - backend: - build: - context: ./backend - dockerfile: Dockerfile - container_name: csf-backend - ports: - - "8000:8000" - environment: - - RUST_LOG=debug - - DATABASE_URL=postgres://csf:csfpassword@postgres:5432/financevault - - JWT_SECRET=supersecretkey_change_me_in_production - - FRONTEND_URL=http://localhost:3000 - depends_on: - postgres: - condition: service_healthy - restart: unless-stopped - - frontend: - build: - context: ./frontend - dockerfile: Dockerfile.prod - container_name: csf-frontend - ports: - - "3000:3000" - environment: - # URL to the backend for client-side requests (browser -> backend) - - PUBLIC_API_BASE_URL=http://localhost:8000 - # Internal URL if SSR needs to talk to backend (optional, handled by public usually if not specified) - - ORIGIN=http://localhost:3000 - depends_on: - - backend - restart: unless-stopped - -volumes: - postgres_data: diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh deleted file mode 100644 index c673e78..0000000 --- a/docker-entrypoint.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash -set -e - -echo "🚀 Starting FinanceVault..." - -# Ensure environment variables are set -export RUST_LOG=${RUST_LOG:-info} -export DATABASE_URL=${DATABASE_URL:-sqlite:/data/finance.db} -export FRONTEND_URL=${FRONTEND_URL:-http://localhost:3000} - -# Check if database directory exists -mkdir -p /data -echo "📁 Data directory: /data" -echo "💾 Database URL: $DATABASE_URL" -echo "🔧 Rust Log Level: $RUST_LOG" -echo "🌐 Frontend URL: $FRONTEND_URL" -echo "" - -# Start frontend (SvelteKit with adapter-node) in background -echo "🎨 Starting Frontend on port 3000..." -cd /app/frontend - -# Start frontend with logs going to stdout (with prefix) -(PORT=3000 HOST=0.0.0.0 ORIGIN=${ORIGIN:-http://localhost:8000} node build/index.js 2>&1 | sed 's/^/[FRONTEND] /') & -FRONTEND_PID=$! - -echo " Frontend PID: $FRONTEND_PID" -echo "" - -# Wait for frontend to start -echo "⏳ Waiting for frontend to initialize..." -sleep 3 - -if ! kill -0 $FRONTEND_PID 2>/dev/null; then - echo "❌ Frontend failed to start!" - exit 1 -fi - -# Check if frontend is responding -MAX_RETRIES=10 -RETRY=0 -while [ $RETRY -lt $MAX_RETRIES ]; do - if curl -f http://localhost:3000/ 2>/dev/null > /dev/null; then - echo "✅ Frontend health check passed" - break - fi - RETRY=$((RETRY+1)) - if [ $RETRY -lt $MAX_RETRIES ]; then - echo "⏳ Frontend not ready yet, retrying ($RETRY/$MAX_RETRIES)..." - sleep 2 - else - echo "⚠️ Frontend health check failed after $MAX_RETRIES attempts (will proceed anyway)" - fi -done - -echo "" - -# Start backend (which proxies to frontend) -echo "📦 Starting Backend on port 8000 (with frontend proxy)..." -cd /app - -# Start backend in foreground with logging -RUST_LOG=$RUST_LOG DATABASE_URL=$DATABASE_URL FRONTEND_URL=$FRONTEND_URL exec ./backend - diff --git a/docs/.github/CICD.md b/docs/.github/CICD.md deleted file mode 100644 index 9328923..0000000 --- a/docs/.github/CICD.md +++ /dev/null @@ -1,194 +0,0 @@ -# CI/CD Workflow Documentation 🚀 - -## Überblick - -Das FinanceVault Projekt nutzt einen **automatisierten Release- und Build-Prozess** mit semantic-release und GitHub Actions. - -## Workflow-Ablauf - -### 1. Release Pipeline (`release.yml`) - -**Trigger:** Push auf den `main` Branch - -**Ablauf:** -1. ✅ Commit-Analyzer prüft Commit-Messages (Conventional Commits) -2. 📊 Bestimmt die neue Version (major/minor/patch) -3. 📝 Generiert CHANGELOG.md -4. 🔄 Aktualisiert Versionen in: - - `package.json` (Root) - - `frontend/package.json` - - `backend/Cargo.toml` -5. 🏷️ Erstellt Git Tag (z.B. `v1.2.3`) -6. 📦 Erstellt GitHub Release -7. ⚙️ Committed Änderungen zurück (`[skip ci]`) - -**Ausgabe:** -- GitHub Release mit Changelog -- Versionierte Dateien im Repository -- Git Tag für Docker Build - -### 2. Docker Build Pipeline (`docker-build-push.yml`) - -**Trigger:** -- Git Tag `v*` (wird vom Release-Workflow erstellt) -- Manueller Trigger (`workflow_dispatch`) - -**Ablauf:** -1. 🏗️ Baut AMD64 Image -2. 🏗️ Baut ARM64 Image -3. 🔗 Erstellt Multi-Arch Manifest -4. 📤 Pushed zu GitHub Container Registry - -**Tags:** -- `v1.2.3` (exakte Version vom Git Tag) -- `v1.2` (Major.Minor) -- `latest` (nur für main branch) -- `main-sha123-amd64` / `main-sha123-arm64` (Arch-spezifisch) - -## Commit Message Format - -Wir verwenden [Conventional Commits](https://www.conventionalcommits.org/): - -``` -(): - - - -