diff --git a/pi/.gitignore b/pi/.gitignore
deleted file mode 100644
index c1c6d40..0000000
--- a/pi/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-/target
-noisebell.service
-/logs
-.env
\ No newline at end of file
diff --git a/pi/Cargo.toml b/pi/Cargo.toml
deleted file mode 100644
index bbcab7d..0000000
--- a/pi/Cargo.toml
+++ /dev/null
@@ -1,26 +0,0 @@
-[package]
-name = "noisebell"
-version = "0.1.0"
-edition = "2021"
-
-[dependencies]
-anyhow = "1.0"
-tokio = { version = "1.45.1", features = ["full"] }
-tracing = "0.1.41"
-tracing-subscriber = "0.3.19"
-rppal = "0.22.1"
-serde = { version = "1.0.219", features = ["derive"] }
-tracing-appender = "0.2.3"
-axum = { version = "0.8.4", features = ["ws"] }
-tower = "0.5.2"
-tower-http = { version = "0.6.2", features = ["fs"] }
-serde_json = "1.0.140"
-regex = "1.11.1"
-chrono = { version = "0.4.41", features = ["serde"] }
-futures = "0.3.31"
-futures-util = "0.3.31"
-url = "2.5.4"
-thiserror = "1.0"
-reqwest = { version = "0.12", features = ["json"] }
-toml = "0.9.5"
-dotenvy = "0.15.7"
diff --git a/pi/README.md b/pi/README.md
deleted file mode 100644
index 0ae8078..0000000
--- a/pi/README.md
+++ /dev/null
@@ -1,180 +0,0 @@
-# Noisebell
-
-A switch monitoring system that detects circuit state changes via GPIO and notifies configured HTTP endpoints via POST requests.
-
-This is build by [Jet Pham][jetpham] to be used at Noisebridge to replace their old discord status bot
-
-## Features
-
-- GPIO circuit monitoring with configurable pin
-- HTTP endpoint notifications via POST requests
-- Daily rotating log files
-- Cross-compilation support for Raspberry Pi deployment
-- Software debouncing to prevent noisy switch detection
-- Concurrent HTTP notifications for improved performance
-- Comprehensive logging and error reporting
-- Web-based monitor for testing (no physical hardware required)
-- **Unified configuration system** with environment variable support
-
-## Configuration
-
-Noisebell uses environment variables for all configuration settings. Copy `env.example` to `.env` and modify the values as needed.
-
-### Environment Variables
-
-All configuration is handled through environment variables. Here are the available options:
-
-#### GPIO Configuration
-- `NOISEBELL_GPIO_PIN` (default: 17) - GPIO pin number for circuit monitoring
-- `NOISEBELL_GPIO_DEBOUNCE_DELAY_SECS` (default: 5) - Debounce delay in seconds
-
-#### Web Monitor Configuration
-- `NOISEBELL_WEB_MONITOR_PORT` (default: 8080) - Port for web monitor server
-- `NOISEBELL_WEB_MONITOR_ENABLED` (default: true) - Enable/disable web monitor
-
-#### Logging Configuration
-- `NOISEBELL_LOGGING_LEVEL` (default: info) - Log level (trace, debug, info, warn, error)
-- `NOISEBELL_LOGGING_FILE_PATH` (default: logs/noisebell.log) - Log file path
-- `NOISEBELL_LOGGING_MAX_BUFFERED_LINES` (default: 10000) - Maximum buffered log lines
-
-#### Monitor Configuration
-- `NOISEBELL_MONITOR_TYPE` (default: web) - Monitor type (gpio, web)
-
-#### Endpoint Configuration
-- `NOISEBELL_ENDPOINT_URL` (default: https://noisebell.jetpham.com/api/status) - HTTP endpoint URL
-- `ENDPOINT_API_KEY` (optional) - API key for Authorization header
-- `NOISEBELL_ENDPOINT_TIMEOUT_SECS` (default: 30) - Request timeout in seconds
-- `NOISEBELL_ENDPOINT_RETRY_ATTEMPTS` (default: 3) - Number of retry attempts
-
-### GPIO and Physical Tech
-
-We interact directly over a [GPIO pin in a pull-up configuration][gpio-pullup] to read whether a circuit has been closed with a switch. This is an extremely simple circuit that will internally call a callback function when the state of the circuit changes.
-
-When a state change is detected, the system:
-
-1. Logs the circuit state change
-2. Sends HTTP POST requests to all configured endpoints
-3. Reports success/failure statistics in the logs
-
-## Debouncing
-
-When a switch changes state, it can bounce and create multiple rapid signals. Debouncing adds a delay to wait for the signal to settle, ensuring we only detect one clean state change instead of multiple false ones.
-
-We do debouncing with software via [`set_async_interupt`][rppal-docs] which handles software debounce for us.
-
-### Logging
-
-Logs are stored in a single continuous log file in the `logs` directory
-
-### Endpoint Notifications
-
-When a circuit state change is detected, the system sends HTTP POST requests to the configured endpoint with the following JSON payload:
-
-```json
-{
- "status": "open"
-}
-```
-
-The status field will be either `"open"` or `"closed"` (lowercase).
-
-#### Endpoint Configuration
-
-The endpoint is configured using the environment variables listed above. If an API key is provided, it will be included in the `Authorization: Bearer ` header.
-
-### Web Monitor
-
-A web-based monitor is available for testing without physical hardware. When `NOISEBELL_WEB_MONITOR_ENABLED=true` (default), you can access the monitor at `http://localhost:8080` to manually trigger state changes and test the endpoint notification system.
-
-### Images
-
-
-
-
-
The knife switch used to detect circuit state changes
-
-
-
-
-
-
-
-
Closeup view of the Raspberry Pi setup
-
-
-
-
-
-
-
-
The complete setup showing the Raspberry Pi mounted in a porthole
-
-
-## Development
-
-### Requirements
-
-- Rust toolchain (Install [Rust][rust-install])
-- Raspberry Pi (tested on [RP02W][rp02w])
-- `cross` for cross-compilation (Install [Cross][cross-install])
-- Internet connectivity (wifi for the rp02w)
-
-### Local Development (Web Monitor)
-
-For local development and testing, you can run the web-based monitor using the following command:
-
-```bash
-# Copy the example environment file
-cp env.example .env
-
-# Run the application
-cargo run
-```
-
-This will start a web server on port 8080. Open your browser and go to [http://localhost:8080](http://localhost:8080) to interact with the web monitor.
-
-This is meant to replace the need for testing on an actual raspberry pi with gpio pins while keeping the terminal clean for logs.
-
-### Deployment
-
-The project includes a deployment script for Raspberry Pi. To deploy, run the deployment script:
-
-```bash
-./deploy.sh
-```
-
-### Configuration Validation
-
-The application validates all configuration values on startup. If any configuration is invalid, the application will exit with a descriptive error message. Common validation checks include:
-
-- GPIO pin must be between 1-40
-- Debounce delay must be greater than 0
-- Monitor type must be either "gpio" or "web"
-- Port numbers must be valid
-- Log levels must be valid (trace, debug, info, warn, error)
-
-### Quick Start
-
-1. **Clone the repository:**
- ```bash
- git clone
- cd noisebell
- ```
-
-2. **Set up environment variables:**
- ```bash
- cp env.example .env
- # Edit .env with your configuration
- ```
-
-3. **Run the application:**
- ```bash
- cargo run
- ```
-
-[jetpham]: https://jetpham.com/
-[gpio-pullup]: https://raspberrypi.stackexchange.com/questions/4569/what-is-a-pull-up-resistor-what-does-it-do-and-why-is-it-needed
-[rppal-docs]: https://docs.rs/rppal/latest/rppal/gpio/struct.InputPin.html#method.set_async_interrupt
-[rust-install]: https://www.rust-lang.org/tools/install
-[rp02w]: https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/
-[cross-install]: https://github.com/cross-rs/cross
diff --git a/pi/configuration.nix b/pi/configuration.nix
new file mode 100644
index 0000000..3609fd0
--- /dev/null
+++ b/pi/configuration.nix
@@ -0,0 +1,39 @@
+{ config, pkgs, ... }:
+
+{
+ system.stateVersion = "24.11";
+
+ networking.hostName = "noisebell";
+
+ # Enable the noisebell service
+ services.noisebell = {
+ enable = true;
+ endpointUrl = "https://example.com/webhook"; # TODO: set your endpoint
+ };
+
+ # Basic system config
+ nix.settings.experimental-features = [ "nix-command" "flakes" ];
+
+ # Tailscale
+ services.tailscale.enable = true;
+
+ # Caddy reverse proxy — proxies to the noisebell status endpoint
+ services.caddy = {
+ enable = true;
+ virtualHosts.":80".extraConfig = ''
+ reverse_proxy localhost:${toString config.services.noisebell.port}
+ '';
+ };
+
+ services.openssh.enable = true;
+
+ # Only allow traffic from Tailscale interface
+ networking.firewall = {
+ trustedInterfaces = [ "tailscale0" ];
+ allowedUDPPorts = [ config.services.tailscale.port ];
+ };
+
+ users.users.root.openssh.authorizedKeys.keys = [
+ # TODO: add your SSH public key
+ ];
+}
diff --git a/pi/deploy.sh b/pi/deploy.sh
deleted file mode 100755
index af340b5..0000000
--- a/pi/deploy.sh
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/bin/bash
-
-# Exit on error
-set -e
-
-echo "Building for Raspberry Pi..."
-cross build --release --target aarch64-unknown-linux-gnu
-
-# Check if Discord credentials are already set
-if [ -z "$DISCORD_TOKEN" ]; then
- echo "Please enter your Discord bot token:"
- read -s DISCORD_TOKEN
-fi
-
-if [ -z "$DISCORD_CHANNEL_ID" ]; then
- echo "Please enter your Discord channel ID:"
- read -s DISCORD_CHANNEL_ID
-fi
-
-# Create service file with credentials
-cat > noisebell.service << EOL
-[Unit]
-Description=Noisebell Discord Notification Service
-After=network.target
-
-[Service]
-Type=simple
-User=noisebridge
-WorkingDirectory=/home/noisebridge
-Environment=DISCORD_TOKEN=${DISCORD_TOKEN}
-Environment=DISCORD_CHANNEL_ID=${DISCORD_CHANNEL_ID}
-ExecStart=/home/noisebridge/noisebell
-Restart=on-failure
-RestartSec=10
-
-[Install]
-WantedBy=multi-user.target
-EOL
-
-echo "Copying to Raspberry Pi..."
-# Debug remote directory status
-ssh noisebridge@noisebell.local "pwd && ls -la ~/ && echo 'Directory permissions:' && stat -c '%A %a %n' ~/"
-# Remove existing files
-ssh noisebridge@noisebell.local "rm -f /home/noisebridge/noisebell /home/noisebridge/noisebell.service"
-# Copy files with absolute paths
-scp -v target/aarch64-unknown-linux-gnu/release/noisebell noisebridge@noisebell.local:/home/noisebridge/noisebell
-scp -v noisebell.service noisebridge@noisebell.local:/home/noisebridge/noisebell.service
-
-echo "Setting up service..."
-# Deploy service
-ssh noisebridge@noisebell.local "sudo cp /home/noisebridge/noisebell.service /etc/systemd/system/ && \
- sudo systemctl daemon-reload && \
- sudo systemctl enable noisebell && \
- sudo systemctl restart noisebell"
-
-# Clean up local service file
-rm noisebell.service
-
-echo "Deployment complete!"
-echo "You can check the service status with: ssh noisebridge@noisebell.local 'sudo systemctl status noisebell'"
diff --git a/pi/env.example b/pi/env.example
deleted file mode 100644
index d7eecb1..0000000
--- a/pi/env.example
+++ /dev/null
@@ -1,26 +0,0 @@
-# Environment variables for noisebell
-# Copy this file to .env and modify as needed
-
-# GPIO Configuration
-NOISEBELL_GPIO_PIN=17
-NOISEBELL_GPIO_DEBOUNCE_DELAY_SECS=5
-
-# Web Monitor Configuration
-NOISEBELL_WEB_MONITOR_PORT=8080
-NOISEBELL_WEB_MONITOR_ENABLED=true
-
-# Logging Configuration
-NOISEBELL_LOGGING_LEVEL=info
-NOISEBELL_LOGGING_FILE_PATH=logs/noisebell.log
-NOISEBELL_LOGGING_MAX_BUFFERED_LINES=10000
-
-# Monitor Configuration
-NOISEBELL_MONITOR_TYPE=web
-
-# Endpoint Configuration
-NOISEBELL_ENDPOINT_URL=https://noisebell.jetpham.com/api/status
-NOISEBELL_ENDPOINT_TIMEOUT_SECS=30
-NOISEBELL_ENDPOINT_RETRY_ATTEMPTS=3
-
-# API key for endpoint notifications (optional)
-ENDPOINT_API_KEY=your_api_key_here
diff --git a/pi/flake.nix b/pi/flake.nix
new file mode 100644
index 0000000..170de1e
--- /dev/null
+++ b/pi/flake.nix
@@ -0,0 +1,81 @@
+{
+ description = "NixOS configuration for noisebell Pi";
+
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+ noisebell.url = "path:./pi-service";
+ };
+
+ outputs = { self, nixpkgs, noisebell }:
+ let
+ nixosModule = { config, lib, pkgs, ... }:
+ let
+ cfg = config.services.noisebell;
+ in
+ {
+ options.services.noisebell = {
+ enable = lib.mkEnableOption "noisebell GPIO door monitor";
+
+ gpioPin = lib.mkOption {
+ type = lib.types.int;
+ default = 17;
+ description = "GPIO pin number to monitor.";
+ };
+
+ debounceSecs = lib.mkOption {
+ type = lib.types.int;
+ default = 5;
+ description = "Debounce delay in seconds.";
+ };
+
+ port = lib.mkOption {
+ type = lib.types.port;
+ default = 8080;
+ description = "HTTP port for the status endpoint.";
+ };
+
+ endpointUrl = lib.mkOption {
+ type = lib.types.str;
+ description = "URL to POST state changes to.";
+ };
+
+ };
+
+ config = lib.mkIf cfg.enable {
+ systemd.services.noisebell = {
+ description = "Noisebell GPIO door monitor";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network-online.target" ];
+ wants = [ "network-online.target" ];
+
+ environment = {
+ NOISEBELL_GPIO_PIN = toString cfg.gpioPin;
+ NOISEBELL_DEBOUNCE_SECS = toString cfg.debounceSecs;
+ NOISEBELL_PORT = toString cfg.port;
+ NOISEBELL_ENDPOINT_URL = cfg.endpointUrl;
+ };
+
+ serviceConfig = {
+ ExecStart = "${noisebell.packages.aarch64-linux.default}/bin/noisebell";
+ Restart = "on-failure";
+ RestartSec = 5;
+ DynamicUser = true;
+ SupplementaryGroups = [ "gpio" ];
+ };
+ };
+ };
+ };
+ in
+ {
+ nixosModules.default = nixosModule;
+
+ nixosConfigurations.pi = nixpkgs.lib.nixosSystem {
+ system = "aarch64-linux";
+ modules = [
+ nixosModule
+ ./configuration.nix
+ ./hardware-configuration.nix
+ ];
+ };
+ };
+}
diff --git a/pi/hardware-configuration.nix b/pi/hardware-configuration.nix
new file mode 100644
index 0000000..35dd3ad
--- /dev/null
+++ b/pi/hardware-configuration.nix
@@ -0,0 +1,22 @@
+{ config, lib, pkgs, modulesPath, ... }:
+
+{
+ # TODO: Replace this file with the output of `nixos-generate-config --show-hardware-config`
+ # on your Raspberry Pi, or use an appropriate hardware module.
+ #
+ # Example for Raspberry Pi 4:
+ #
+ # imports = [ "${modulesPath}/installer/sd-card/sd-image-aarch64.nix" ];
+ #
+ # hardware.enableRedistributableFirmware = true;
+
+ imports = [ ];
+
+ boot.loader.grub.enable = false;
+ boot.loader.generic-extlinux-compatible.enable = true;
+
+ fileSystems."/" = {
+ device = "/dev/disk/by-label/NIXOS_SD";
+ fsType = "ext4";
+ };
+}
diff --git a/pi/media/closed.png b/pi/media/closed.png
deleted file mode 100644
index fa6bff1..0000000
Binary files a/pi/media/closed.png and /dev/null differ
diff --git a/pi/media/noisebell knifeswitch.jpg b/pi/media/noisebell knifeswitch.jpg
deleted file mode 100644
index 1271dd6..0000000
Binary files a/pi/media/noisebell knifeswitch.jpg and /dev/null differ
diff --git a/pi/media/noisebell logo.ico b/pi/media/noisebell logo.ico
deleted file mode 100644
index b9f31a3..0000000
Binary files a/pi/media/noisebell logo.ico and /dev/null differ
diff --git a/pi/media/noisebell logo.svg b/pi/media/noisebell logo.svg
deleted file mode 100644
index 27d17c8..0000000
--- a/pi/media/noisebell logo.svg
+++ /dev/null
@@ -1,161 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/pi/media/noisebell raspberrypi closeup.jpg b/pi/media/noisebell raspberrypi closeup.jpg
deleted file mode 100644
index ec7bfff..0000000
Binary files a/pi/media/noisebell raspberrypi closeup.jpg and /dev/null differ
diff --git a/pi/media/noisebell raspberrypi with porthole.jpg b/pi/media/noisebell raspberrypi with porthole.jpg
deleted file mode 100644
index b947642..0000000
Binary files a/pi/media/noisebell raspberrypi with porthole.jpg and /dev/null differ
diff --git a/pi/media/open.png b/pi/media/open.png
deleted file mode 100644
index 8a9bbd9..0000000
Binary files a/pi/media/open.png and /dev/null differ
diff --git a/pi/.cargo/config.toml b/pi/pi-service/.cargo/config.toml
similarity index 100%
rename from pi/.cargo/config.toml
rename to pi/pi-service/.cargo/config.toml
diff --git a/pi/Cargo.lock b/pi/pi-service/Cargo.lock
similarity index 56%
rename from pi/Cargo.lock
rename to pi/pi-service/Cargo.lock
index a11a540..b0929ab 100644
--- a/pi/Cargo.lock
+++ b/pi/pi-service/Cargo.lock
@@ -2,50 +2,11 @@
# It is not intended for manual editing.
version = 4
-[[package]]
-name = "addr2line"
-version = "0.24.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
-dependencies = [
- "gimli",
-]
-
-[[package]]
-name = "adler2"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
-
-[[package]]
-name = "aho-corasick"
-version = "1.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "android-tzdata"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
-
-[[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.98"
+version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "atomic-waker"
@@ -53,20 +14,13 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
-[[package]]
-name = "autocfg"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
-
[[package]]
name = "axum"
-version = "0.8.4"
+version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5"
+checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
dependencies = [
"axum-core",
- "base64",
"bytes",
"form_urlencoded",
"futures-util",
@@ -81,15 +35,12 @@ dependencies = [
"mime",
"percent-encoding",
"pin-project-lite",
- "rustversion",
- "serde",
+ "serde_core",
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
- "sha1",
"sync_wrapper",
"tokio",
- "tokio-tungstenite",
"tower",
"tower-layer",
"tower-service",
@@ -98,9 +49,9 @@ dependencies = [
[[package]]
name = "axum-core"
-version = "0.5.2"
+version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6"
+checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"
dependencies = [
"bytes",
"futures-core",
@@ -109,28 +60,12 @@ dependencies = [
"http-body-util",
"mime",
"pin-project-lite",
- "rustversion",
"sync_wrapper",
"tower-layer",
"tower-service",
"tracing",
]
-[[package]]
-name = "backtrace"
-version = "0.3.75"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
-dependencies = [
- "addr2line",
- "cfg-if",
- "libc",
- "miniz_oxide",
- "object",
- "rustc-demangle",
- "windows-targets",
-]
-
[[package]]
name = "base64"
version = "0.22.1"
@@ -139,60 +74,37 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
-version = "2.9.1"
+version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
-
-[[package]]
-name = "block-buffer"
-version = "0.10.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
-dependencies = [
- "generic-array",
-]
+checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
[[package]]
name = "bumpalo"
-version = "3.18.1"
+version = "3.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee"
+checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
[[package]]
name = "bytes"
-version = "1.10.1"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
+checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]]
name = "cc"
-version = "1.2.26"
+version = "1.2.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac"
+checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
dependencies = [
+ "find-msvc-tools",
"shlex",
]
[[package]]
name = "cfg-if"
-version = "1.0.0"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "chrono"
-version = "0.4.41"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
-dependencies = [
- "android-tzdata",
- "iana-time-zone",
- "js-sys",
- "num-traits",
- "serde",
- "wasm-bindgen",
- "windows-link",
-]
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "core-foundation"
@@ -205,69 +117,20 @@ dependencies = [
]
[[package]]
-name = "core-foundation-sys"
-version = "0.8.7"
+name = "core-foundation"
+version = "0.10.1"
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"
+checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
dependencies = [
+ "core-foundation-sys",
"libc",
]
[[package]]
-name = "crossbeam-channel"
-version = "0.5.15"
+name = "core-foundation-sys"
+version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
-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 = "crypto-common"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
-dependencies = [
- "generic-array",
- "typenum",
-]
-
-[[package]]
-name = "data-encoding"
-version = "2.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
-
-[[package]]
-name = "deranged"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
-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",
-]
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "displaydoc"
@@ -280,12 +143,6 @@ dependencies = [
"syn",
]
-[[package]]
-name = "dotenvy"
-version = "0.15.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
-
[[package]]
name = "encoding_rs"
version = "0.8.35"
@@ -303,12 +160,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
-version = "0.3.13"
+version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
- "windows-sys 0.59.0",
+ "windows-sys 0.61.2",
]
[[package]]
@@ -317,12 +174,24 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
+
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+[[package]]
+name = "foldhash"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
[[package]]
name = "foreign-types"
version = "0.3.2"
@@ -340,146 +209,81 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
-version = "1.2.1"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
dependencies = [
"percent-encoding",
]
-[[package]]
-name = "futures"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
-dependencies = [
- "futures-channel",
- "futures-core",
- "futures-executor",
- "futures-io",
- "futures-sink",
- "futures-task",
- "futures-util",
-]
-
[[package]]
name = "futures-channel"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
+checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
dependencies = [
"futures-core",
- "futures-sink",
]
[[package]]
name = "futures-core"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
-
-[[package]]
-name = "futures-executor"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
-dependencies = [
- "futures-core",
- "futures-task",
- "futures-util",
-]
-
-[[package]]
-name = "futures-io"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
-
-[[package]]
-name = "futures-macro"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
+checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
[[package]]
name = "futures-sink"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
+checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
[[package]]
name = "futures-task"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
+checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
[[package]]
name = "futures-util"
-version = "0.3.31"
+version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
+checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
dependencies = [
- "futures-channel",
"futures-core",
- "futures-io",
- "futures-macro",
- "futures-sink",
"futures-task",
- "memchr",
"pin-project-lite",
- "pin-utils",
"slab",
]
-[[package]]
-name = "generic-array"
-version = "0.14.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
-dependencies = [
- "typenum",
- "version_check",
-]
-
[[package]]
name = "getrandom"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
+checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
"cfg-if",
"libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi",
]
[[package]]
name = "getrandom"
-version = "0.3.3"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
+checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
dependencies = [
"cfg-if",
"libc",
"r-efi",
- "wasi 0.14.2+wasi-0.2.4",
+ "wasip2",
+ "wasip3",
]
-[[package]]
-name = "gimli"
-version = "0.31.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
-
[[package]]
name = "h2"
-version = "0.4.11"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785"
+checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54"
dependencies = [
"atomic-waker",
"bytes",
@@ -496,18 +300,32 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.15.4"
+version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
+dependencies = [
+ "foldhash",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "http"
-version = "1.3.1"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
+checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
dependencies = [
"bytes",
- "fnv",
"itoa",
]
@@ -534,12 +352,6 @@ dependencies = [
"pin-project-lite",
]
-[[package]]
-name = "http-range-header"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c"
-
[[package]]
name = "httparse"
version = "1.10.1"
@@ -554,13 +366,14 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
-version = "1.6.0"
+version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
+checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11"
dependencies = [
+ "atomic-waker",
"bytes",
"futures-channel",
- "futures-util",
+ "futures-core",
"h2",
"http",
"http-body",
@@ -568,6 +381,7 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
+ "pin-utils",
"smallvec",
"tokio",
"want",
@@ -607,14 +421,13 @@ dependencies = [
[[package]]
name = "hyper-util"
-version = "0.1.14"
+version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb"
+checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
dependencies = [
"base64",
"bytes",
"futures-channel",
- "futures-core",
"futures-util",
"http",
"http-body",
@@ -631,35 +444,11 @@ dependencies = [
"windows-registry",
]
-[[package]]
-name = "iana-time-zone"
-version = "0.1.63"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
-dependencies = [
- "android_system_properties",
- "core-foundation-sys",
- "iana-time-zone-haiku",
- "js-sys",
- "log",
- "wasm-bindgen",
- "windows-core",
-]
-
-[[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.0.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
+checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
dependencies = [
"displaydoc",
"potential_utf",
@@ -670,9 +459,9 @@ dependencies = [
[[package]]
name = "icu_locale_core"
-version = "2.0.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
+checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
dependencies = [
"displaydoc",
"litemap",
@@ -683,11 +472,10 @@ dependencies = [
[[package]]
name = "icu_normalizer"
-version = "2.0.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
+checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
dependencies = [
- "displaydoc",
"icu_collections",
"icu_normalizer_data",
"icu_properties",
@@ -698,42 +486,38 @@ dependencies = [
[[package]]
name = "icu_normalizer_data"
-version = "2.0.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
+checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
[[package]]
name = "icu_properties"
-version = "2.0.1"
+version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b"
+checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec"
dependencies = [
- "displaydoc",
"icu_collections",
"icu_locale_core",
"icu_properties_data",
"icu_provider",
- "potential_utf",
"zerotrie",
"zerovec",
]
[[package]]
name = "icu_properties_data"
-version = "2.0.1"
+version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"
+checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af"
[[package]]
name = "icu_provider"
-version = "2.0.0"
+version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
+checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
dependencies = [
"displaydoc",
"icu_locale_core",
- "stable_deref_trait",
- "tinystr",
"writeable",
"yoke",
"zerofrom",
@@ -742,10 +526,16 @@ dependencies = [
]
[[package]]
-name = "idna"
-version = "1.0.3"
+name = "id-arena"
+version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
+checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
+
+[[package]]
+name = "idna"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
dependencies = [
"idna_adapter",
"smallvec",
@@ -764,25 +554,27 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.10.0"
+version = "2.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
+checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
dependencies = [
"equivalent",
- "hashbrown",
+ "hashbrown 0.16.1",
+ "serde",
+ "serde_core",
]
[[package]]
name = "ipnet"
-version = "2.11.0"
+version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
+checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
[[package]]
name = "iri-string"
-version = "0.7.8"
+version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2"
+checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a"
dependencies = [
"memchr",
"serde",
@@ -790,15 +582,15 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.15"
+version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
[[package]]
name = "js-sys"
-version = "0.3.77"
+version = "0.3.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
+checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c"
dependencies = [
"once_cell",
"wasm-bindgen",
@@ -811,38 +603,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
-name = "libc"
-version = "0.2.172"
+name = "leb128fmt"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
+checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
+
+[[package]]
+name = "libc"
+version = "0.2.182"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
[[package]]
name = "linux-raw-sys"
-version = "0.9.4"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
+checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
[[package]]
name = "litemap"
-version = "0.8.0"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
+checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
[[package]]
name = "lock_api"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
+checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
dependencies = [
- "autocfg",
"scopeguard",
]
[[package]]
name = "log"
-version = "0.4.27"
+version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "matchit"
@@ -852,9 +649,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "memchr"
-version = "2.7.4"
+version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "mime"
@@ -862,41 +659,22 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
-[[package]]
-name = "mime_guess"
-version = "2.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
-dependencies = [
- "mime",
- "unicase",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
-dependencies = [
- "adler2",
-]
-
[[package]]
name = "mio"
-version = "1.0.4"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
+checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
dependencies = [
"libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys 0.59.0",
+ "wasi",
+ "windows-sys 0.61.2",
]
[[package]]
name = "native-tls"
-version = "0.2.14"
+version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
+checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2"
dependencies = [
"libc",
"log",
@@ -915,58 +693,22 @@ version = "0.1.0"
dependencies = [
"anyhow",
"axum",
- "chrono",
- "dotenvy",
- "futures",
- "futures-util",
- "regex",
"reqwest",
"rppal",
"serde",
"serde_json",
- "thiserror 1.0.69",
"tokio",
- "toml",
- "tower",
- "tower-http",
"tracing",
- "tracing-appender",
"tracing-subscriber",
- "url",
]
[[package]]
name = "nu-ansi-term"
-version = "0.46.0"
+version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
- "overload",
- "winapi",
-]
-
-[[package]]
-name = "num-conv"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
-
-[[package]]
-name = "num-traits"
-version = "0.2.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "object"
-version = "0.36.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
-dependencies = [
- "memchr",
+ "windows-sys 0.61.2",
]
[[package]]
@@ -977,9 +719,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "openssl"
-version = "0.10.73"
+version = "0.10.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
+checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328"
dependencies = [
"bitflags",
"cfg-if",
@@ -1003,15 +745,15 @@ dependencies = [
[[package]]
name = "openssl-probe"
-version = "0.1.6"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
+checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
[[package]]
name = "openssl-sys"
-version = "0.9.109"
+version = "0.9.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
+checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321"
dependencies = [
"cc",
"libc",
@@ -1019,17 +761,11 @@ dependencies = [
"vcpkg",
]
-[[package]]
-name = "overload"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
-
[[package]]
name = "parking_lot"
-version = "0.12.4"
+version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
+checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -1037,28 +773,28 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.11"
+version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
+checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
- "windows-targets",
+ "windows-link",
]
[[package]]
name = "percent-encoding"
-version = "2.3.1"
+version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "pin-project-lite"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "pin-utils"
@@ -1074,124 +810,61 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "potential_utf"
-version = "0.1.2"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
+checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
dependencies = [
"zerovec",
]
[[package]]
-name = "powerfmt"
-version = "0.2.0"
+name = "prettyplease"
+version = "0.2.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
- "zerocopy",
+ "proc-macro2",
+ "syn",
]
[[package]]
name = "proc-macro2"
-version = "1.0.95"
+version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.40"
+version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
-version = "5.2.0"
+version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
-
-[[package]]
-name = "rand"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
-dependencies = [
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
-dependencies = [
- "getrandom 0.3.3",
-]
+checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "redox_syscall"
-version = "0.5.12"
+version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags",
]
-[[package]]
-name = "regex"
-version = "1.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
-
[[package]]
name = "reqwest"
-version = "0.12.22"
+version = "0.12.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531"
+checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
dependencies = [
"base64",
"bytes",
@@ -1235,7 +908,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
dependencies = [
"cc",
"cfg-if",
- "getrandom 0.2.16",
+ "getrandom 0.2.17",
"libc",
"untrusted",
"windows-sys 0.52.0",
@@ -1250,30 +923,24 @@ dependencies = [
"libc",
]
-[[package]]
-name = "rustc-demangle"
-version = "0.1.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
-
[[package]]
name = "rustix"
-version = "1.0.8"
+version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
+checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
- "windows-sys 0.59.0",
+ "windows-sys 0.61.2",
]
[[package]]
name = "rustls"
-version = "0.23.29"
+version = "0.23.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1"
+checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4"
dependencies = [
"once_cell",
"rustls-pki-types",
@@ -1284,18 +951,18 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
-version = "1.12.0"
+version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
+checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
dependencies = [
"zeroize",
]
[[package]]
name = "rustls-webpki"
-version = "0.103.4"
+version = "0.103.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc"
+checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53"
dependencies = [
"ring",
"rustls-pki-types",
@@ -1304,23 +971,23 @@ dependencies = [
[[package]]
name = "rustversion"
-version = "1.0.21"
+version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ryu"
-version = "1.0.20"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
[[package]]
name = "schannel"
-version = "0.1.27"
+version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
+checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1"
dependencies = [
- "windows-sys 0.59.0",
+ "windows-sys 0.61.2",
]
[[package]]
@@ -1331,12 +998,12 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "security-framework"
-version = "2.11.1"
+version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
+checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [
"bitflags",
- "core-foundation",
+ "core-foundation 0.10.1",
"core-foundation-sys",
"libc",
"security-framework-sys",
@@ -1344,28 +1011,44 @@ dependencies = [
[[package]]
name = "security-framework-sys"
-version = "2.14.0"
+version = "2.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
+checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
-name = "serde"
-version = "1.0.219"
+name = "semver"
+version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
+
+[[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.219"
+version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
@@ -1374,33 +1057,26 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.140"
+version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [
"itoa",
"memchr",
- "ryu",
"serde",
+ "serde_core",
+ "zmij",
]
[[package]]
name = "serde_path_to_error"
-version = "0.1.17"
+version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a"
+checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
dependencies = [
"itoa",
"serde",
-]
-
-[[package]]
-name = "serde_spanned"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83"
-dependencies = [
- "serde",
+ "serde_core",
]
[[package]]
@@ -1415,17 +1091,6 @@ dependencies = [
"serde",
]
-[[package]]
-name = "sha1"
-version = "0.10.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "digest",
-]
-
[[package]]
name = "sharded-slab"
version = "0.1.7"
@@ -1443,21 +1108,19 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
-version = "1.4.5"
+version = "1.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
+checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
dependencies = [
+ "errno",
"libc",
]
[[package]]
name = "slab"
-version = "0.4.9"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
-dependencies = [
- "autocfg",
-]
+checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "smallvec"
@@ -1467,19 +1130,19 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "socket2"
-version = "0.5.10"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
+checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.60.2",
]
[[package]]
name = "stable_deref_trait"
-version = "1.2.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
[[package]]
name = "subtle"
@@ -1489,9 +1152,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
-version = "2.0.101"
+version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
@@ -1520,12 +1183,12 @@ dependencies = [
[[package]]
name = "system-configuration"
-version = "0.6.1"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
+checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
dependencies = [
"bitflags",
- "core-foundation",
+ "core-foundation 0.9.4",
"system-configuration-sys",
]
@@ -1541,103 +1204,31 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.20.0"
+version = "3.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
+checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0"
dependencies = [
"fastrand",
- "getrandom 0.3.3",
+ "getrandom 0.4.2",
"once_cell",
"rustix",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "thiserror"
-version = "1.0.69"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
-dependencies = [
- "thiserror-impl 1.0.69",
-]
-
-[[package]]
-name = "thiserror"
-version = "2.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
-dependencies = [
- "thiserror-impl 2.0.12",
-]
-
-[[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 = "thiserror-impl"
-version = "2.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "windows-sys 0.61.2",
]
[[package]]
name = "thread_local"
-version = "1.1.8"
+version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
+checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
- "once_cell",
-]
-
-[[package]]
-name = "time"
-version = "0.3.41"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
-dependencies = [
- "deranged",
- "itoa",
- "num-conv",
- "powerfmt",
- "serde",
- "time-core",
- "time-macros",
-]
-
-[[package]]
-name = "time-core"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
-
-[[package]]
-name = "time-macros"
-version = "0.2.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
-dependencies = [
- "num-conv",
- "time-core",
]
[[package]]
name = "tinystr"
-version = "0.8.1"
+version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
+checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
dependencies = [
"displaydoc",
"zerovec",
@@ -1645,11 +1236,10 @@ dependencies = [
[[package]]
name = "tokio"
-version = "1.45.1"
+version = "1.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779"
+checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
dependencies = [
- "backtrace",
"bytes",
"libc",
"mio",
@@ -1658,14 +1248,14 @@ dependencies = [
"signal-hook-registry",
"socket2",
"tokio-macros",
- "windows-sys 0.52.0",
+ "windows-sys 0.61.2",
]
[[package]]
name = "tokio-macros"
-version = "2.5.0"
+version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
+checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c"
dependencies = [
"proc-macro2",
"quote",
@@ -1684,31 +1274,19 @@ dependencies = [
[[package]]
name = "tokio-rustls"
-version = "0.26.2"
+version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
+checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61"
dependencies = [
"rustls",
"tokio",
]
-[[package]]
-name = "tokio-tungstenite"
-version = "0.26.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084"
-dependencies = [
- "futures-util",
- "log",
- "tokio",
- "tungstenite",
-]
-
[[package]]
name = "tokio-util"
-version = "0.7.15"
+version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
+checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
dependencies = [
"bytes",
"futures-core",
@@ -1717,50 +1295,11 @@ dependencies = [
"tokio",
]
-[[package]]
-name = "toml"
-version = "0.9.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8"
-dependencies = [
- "indexmap",
- "serde",
- "serde_spanned",
- "toml_datetime",
- "toml_parser",
- "toml_writer",
- "winnow",
-]
-
-[[package]]
-name = "toml_datetime"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "toml_parser"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10"
-dependencies = [
- "winnow",
-]
-
-[[package]]
-name = "toml_writer"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64"
-
[[package]]
name = "tower"
-version = "0.5.2"
+version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
+checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"
dependencies = [
"futures-core",
"futures-util",
@@ -1774,30 +1313,20 @@ dependencies = [
[[package]]
name = "tower-http"
-version = "0.6.6"
+version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
+checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
dependencies = [
"bitflags",
"bytes",
- "futures-core",
"futures-util",
"http",
"http-body",
- "http-body-util",
- "http-range-header",
- "httpdate",
"iri-string",
- "mime",
- "mime_guess",
- "percent-encoding",
"pin-project-lite",
- "tokio",
- "tokio-util",
"tower",
"tower-layer",
"tower-service",
- "tracing",
]
[[package]]
@@ -1814,9 +1343,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
[[package]]
name = "tracing"
-version = "0.1.41"
+version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
+checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"log",
"pin-project-lite",
@@ -1824,23 +1353,11 @@ dependencies = [
"tracing-core",
]
-[[package]]
-name = "tracing-appender"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf"
-dependencies = [
- "crossbeam-channel",
- "thiserror 1.0.69",
- "time",
- "tracing-subscriber",
-]
-
[[package]]
name = "tracing-attributes"
-version = "0.1.29"
+version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662"
+checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
@@ -1849,9 +1366,9 @@ dependencies = [
[[package]]
name = "tracing-core"
-version = "0.1.34"
+version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
+checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
"valuable",
@@ -1870,9 +1387,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
-version = "0.3.19"
+version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
+checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
dependencies = [
"nu-ansi-term",
"sharded-slab",
@@ -1888,40 +1405,17 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
-[[package]]
-name = "tungstenite"
-version = "0.26.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13"
-dependencies = [
- "bytes",
- "data-encoding",
- "http",
- "httparse",
- "log",
- "rand",
- "sha1",
- "thiserror 2.0.12",
- "utf-8",
-]
-
-[[package]]
-name = "typenum"
-version = "1.18.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
-
-[[package]]
-name = "unicase"
-version = "2.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
-
[[package]]
name = "unicode-ident"
-version = "1.0.18"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "untrusted"
@@ -1931,21 +1425,16 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "url"
-version = "2.5.4"
+version = "2.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
+checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
+ "serde",
]
-[[package]]
-name = "utf-8"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
-
[[package]]
name = "utf8_iter"
version = "1.0.4"
@@ -1964,12 +1453,6 @@ 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"
@@ -1981,52 +1464,49 @@ dependencies = [
[[package]]
name = "wasi"
-version = "0.11.0+wasi-snapshot-preview1"
+version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
-name = "wasi"
-version = "0.14.2+wasi-0.2.4"
+name = "wasip2"
+version = "1.0.2+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
dependencies = [
- "wit-bindgen-rt",
+ "wit-bindgen",
+]
+
+[[package]]
+name = "wasip3"
+version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
+dependencies = [
+ "wit-bindgen",
]
[[package]]
name = "wasm-bindgen"
-version = "0.2.100"
+version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
+checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
-dependencies = [
- "bumpalo",
- "log",
- "proc-macro2",
- "quote",
- "syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.50"
+version = "0.4.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61"
+checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8"
dependencies = [
"cfg-if",
+ "futures-util",
"js-sys",
"once_cell",
"wasm-bindgen",
@@ -2035,9 +1515,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.100"
+version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
+checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2045,104 +1525,81 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.100"
+version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
+checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3"
dependencies = [
+ "bumpalo",
"proc-macro2",
"quote",
"syn",
- "wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.100"
+version = "0.2.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16"
dependencies = [
"unicode-ident",
]
[[package]]
-name = "web-sys"
-version = "0.3.77"
+name = "wasm-encoder"
+version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
+checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
+dependencies = [
+ "leb128fmt",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasm-metadata"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
+dependencies = [
+ "anyhow",
+ "indexmap",
+ "wasm-encoder",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
+dependencies = [
+ "bitflags",
+ "hashbrown 0.15.5",
+ "indexmap",
+ "semver",
+]
+
+[[package]]
+name = "web-sys"
+version = "0.3.91"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9"
dependencies = [
"js-sys",
"wasm-bindgen",
]
-[[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-core"
-version = "0.61.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
-dependencies = [
- "windows-implement",
- "windows-interface",
- "windows-link",
- "windows-result",
- "windows-strings",
-]
-
-[[package]]
-name = "windows-implement"
-version = "0.60.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "windows-interface"
-version = "0.59.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
[[package]]
name = "windows-link"
-version = "0.1.1"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-registry"
-version = "0.5.2"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820"
+checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720"
dependencies = [
"windows-link",
"windows-result",
@@ -2151,18 +1608,18 @@ dependencies = [
[[package]]
name = "windows-result"
-version = "0.3.4"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
+checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
-version = "0.4.2"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
+checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
"windows-link",
]
@@ -2173,16 +1630,25 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets",
+ "windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
-version = "0.59.0"
+version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
- "windows-targets",
+ "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]]
@@ -2191,14 +1657,31 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "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]]
@@ -2207,42 +1690,84 @@ 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"
@@ -2250,33 +1775,111 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
-name = "winnow"
-version = "0.7.12"
+name = "windows_x86_64_msvc"
+version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
+checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
-name = "wit-bindgen-rt"
-version = "0.39.0"
+name = "wit-bindgen"
+version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
+checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
dependencies = [
+ "wit-bindgen-rust-macro",
+]
+
+[[package]]
+name = "wit-bindgen-core"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
+dependencies = [
+ "anyhow",
+ "heck",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-bindgen-rust"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
+dependencies = [
+ "anyhow",
+ "heck",
+ "indexmap",
+ "prettyplease",
+ "syn",
+ "wasm-metadata",
+ "wit-bindgen-core",
+ "wit-component",
+]
+
+[[package]]
+name = "wit-bindgen-rust-macro"
+version = "0.51.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
+dependencies = [
+ "anyhow",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wit-bindgen-core",
+ "wit-bindgen-rust",
+]
+
+[[package]]
+name = "wit-component"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
+dependencies = [
+ "anyhow",
"bitflags",
+ "indexmap",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "wasm-encoder",
+ "wasm-metadata",
+ "wasmparser",
+ "wit-parser",
+]
+
+[[package]]
+name = "wit-parser"
+version = "0.244.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
+dependencies = [
+ "anyhow",
+ "id-arena",
+ "indexmap",
+ "log",
+ "semver",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "unicode-xid",
+ "wasmparser",
]
[[package]]
name = "writeable"
-version = "0.6.1"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
+checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
[[package]]
name = "yoke"
-version = "0.8.0"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
+checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
dependencies = [
- "serde",
"stable_deref_trait",
"yoke-derive",
"zerofrom",
@@ -2284,9 +1887,9 @@ dependencies = [
[[package]]
name = "yoke-derive"
-version = "0.8.0"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
+checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [
"proc-macro2",
"quote",
@@ -2294,26 +1897,6 @@ dependencies = [
"synstructure",
]
-[[package]]
-name = "zerocopy"
-version = "0.8.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
-dependencies = [
- "zerocopy-derive",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.8.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
[[package]]
name = "zerofrom"
version = "0.1.6"
@@ -2337,15 +1920,15 @@ dependencies = [
[[package]]
name = "zeroize"
-version = "1.8.1"
+version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
[[package]]
name = "zerotrie"
-version = "0.2.2"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
+checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
dependencies = [
"displaydoc",
"yoke",
@@ -2354,9 +1937,9 @@ dependencies = [
[[package]]
name = "zerovec"
-version = "0.11.2"
+version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
+checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
dependencies = [
"yoke",
"zerofrom",
@@ -2365,11 +1948,17 @@ dependencies = [
[[package]]
name = "zerovec-derive"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
+checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
+
+[[package]]
+name = "zmij"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
diff --git a/pi/pi-service/Cargo.toml b/pi/pi-service/Cargo.toml
new file mode 100644
index 0000000..3d31271
--- /dev/null
+++ b/pi/pi-service/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "noisebell"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+anyhow = "1.0"
+axum = "0.8"
+reqwest = { version = "0.12", features = ["json"] }
+rppal = "0.22"
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+tokio = { version = "1", features = ["full"] }
+tracing = "0.1"
+tracing-subscriber = "0.3"
diff --git a/pi/pi-service/flake.nix b/pi/pi-service/flake.nix
new file mode 100644
index 0000000..812dc56
--- /dev/null
+++ b/pi/pi-service/flake.nix
@@ -0,0 +1,62 @@
+{
+ description = "Noisebell - GPIO door monitor service";
+
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+ crane.url = "github:ipetkov/crane";
+ rust-overlay = {
+ url = "github:oxalica/rust-overlay";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+ };
+
+ outputs = { self, nixpkgs, crane, rust-overlay }:
+ let
+ forSystem = system:
+ let
+ pkgs = import nixpkgs {
+ inherit system;
+ overlays = [ rust-overlay.overlays.default ];
+ };
+
+ crossPkgs = import nixpkgs {
+ inherit system;
+ crossSystem.config = "aarch64-unknown-linux-gnu";
+ overlays = [ rust-overlay.overlays.default ];
+ };
+
+ rustToolchain = pkgs.rust-bin.stable.latest.default.override {
+ targets = [ "aarch64-unknown-linux-gnu" ];
+ };
+
+ craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain;
+
+ src = craneLib.cleanCargoSource ./.;
+
+ commonArgs = {
+ inherit src;
+ strictDeps = true;
+ doCheck = false;
+
+ CARGO_BUILD_TARGET = "aarch64-unknown-linux-gnu";
+ CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER =
+ "${crossPkgs.stdenv.cc.targetPrefix}cc";
+
+ HOST_CC = "${pkgs.stdenv.cc.nativePrefix}cc";
+
+ depsBuildBuild = [ crossPkgs.stdenv.cc ];
+ };
+
+ cargoArtifacts = craneLib.buildDepsOnly commonArgs;
+
+ noisebell = craneLib.buildPackage (commonArgs // {
+ inherit cargoArtifacts;
+ });
+ in
+ {
+ packages.aarch64-linux.default = noisebell;
+ packages.aarch64-linux.noisebell = noisebell;
+ };
+ in
+ forSystem "x86_64-linux";
+}
diff --git a/pi/pi-service/src/main.rs b/pi/pi-service/src/main.rs
new file mode 100644
index 0000000..f63f4a6
--- /dev/null
+++ b/pi/pi-service/src/main.rs
@@ -0,0 +1,116 @@
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::Arc;
+use std::time::Duration;
+
+use anyhow::{Context, Result};
+use axum::{extract::State, routing::get, Json, Router};
+use rppal::gpio::{Gpio, Level, Trigger};
+use serde::Serialize;
+use tracing::{error, info};
+
+#[derive(Serialize)]
+struct StatusResponse {
+ status: &'static str,
+}
+
+fn status_str(is_open: bool) -> &'static str {
+ if is_open {
+ "open"
+ } else {
+ "closed"
+ }
+}
+
+async fn get_status(State(is_open): State>) -> Json {
+ Json(StatusResponse {
+ status: status_str(is_open.load(Ordering::Relaxed)),
+ })
+}
+
+#[tokio::main]
+async fn main() -> Result<()> {
+ tracing_subscriber::fmt::init();
+
+ let gpio_pin: u8 = std::env::var("NOISEBELL_GPIO_PIN")
+ .unwrap_or_else(|_| "17".into())
+ .parse()
+ .context("NOISEBELL_GPIO_PIN must be a valid u8")?;
+
+ let debounce_secs: u64 = std::env::var("NOISEBELL_DEBOUNCE_SECS")
+ .unwrap_or_else(|_| "5".into())
+ .parse()
+ .context("NOISEBELL_DEBOUNCE_SECS must be a valid u64")?;
+
+ let port: u16 = std::env::var("NOISEBELL_PORT")
+ .unwrap_or_else(|_| "8080".into())
+ .parse()
+ .context("NOISEBELL_PORT must be a valid u16")?;
+
+ let endpoint_url =
+ std::env::var("NOISEBELL_ENDPOINT_URL").context("NOISEBELL_ENDPOINT_URL is required")?;
+
+ info!(gpio_pin, debounce_secs, port, %endpoint_url, "starting noisebell");
+
+ let gpio = Gpio::new().context("failed to initialize GPIO")?;
+ let pin = gpio
+ .get(gpio_pin)
+ .context(format!("failed to get GPIO pin {gpio_pin}"))?
+ .into_input_pullup();
+
+ let is_open = Arc::new(AtomicBool::new(pin.read() == Level::Low));
+
+ info!(initial_status = status_str(is_open.load(Ordering::Relaxed)), "GPIO initialized");
+
+ // Channel to bridge sync GPIO callback -> async notification task
+ let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::();
+
+ // Set up async interrupt for state changes
+ let state_for_interrupt = is_open.clone();
+ pin.set_async_interrupt(
+ Trigger::Both,
+ Some(Duration::from_secs(debounce_secs)),
+ move |event| {
+ let new_open = match event.trigger {
+ Trigger::FallingEdge => true,
+ Trigger::RisingEdge => false,
+ _ => return,
+ };
+ let was_open = state_for_interrupt.swap(new_open, Ordering::Relaxed);
+ if was_open != new_open {
+ let _ = tx.send(new_open);
+ }
+ },
+ )
+ .context("failed to set GPIO interrupt")?;
+
+ // Task that POSTs state changes to the endpoint
+ tokio::spawn(async move {
+ let client = reqwest::Client::new();
+ while let Some(new_open) = rx.recv().await {
+ let status = status_str(new_open);
+ info!(status, "state changed");
+
+ if let Err(e) = client
+ .post(&endpoint_url)
+ .json(&serde_json::json!({ "status": status }))
+ .send()
+ .await
+ {
+ error!(%e, "failed to notify endpoint");
+ }
+ }
+ });
+
+ let app = Router::new()
+ .route("/status", get(get_status))
+ .with_state(is_open);
+
+ let listener = tokio::net::TcpListener::bind(("0.0.0.0", port))
+ .await
+ .context(format!("failed to bind to port {port}"))?;
+
+ info!(port, "listening");
+ axum::serve(listener, app).await.context("server error")?;
+
+ Ok(())
+}
diff --git a/pi/src/config.rs b/pi/src/config.rs
deleted file mode 100644
index af4a476..0000000
--- a/pi/src/config.rs
+++ /dev/null
@@ -1,195 +0,0 @@
-use serde::{Deserialize, Serialize};
-use std::time::Duration;
-use anyhow::Result;
-use dotenvy::dotenv;
-use tracing::info;
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct Config {
- pub gpio: GpioConfig,
- pub web_monitor: WebMonitorConfig,
- pub logging: LoggingConfig,
- pub monitor: MonitorConfig,
- pub endpoint: EndpointConfig,
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct GpioConfig {
- pub pin: u8,
- pub debounce_delay_secs: u64,
-}
-
-impl GpioConfig {
- pub fn from_env() -> Result {
- let pin = std::env::var("NOISEBELL_GPIO_PIN")
- .unwrap_or_else(|_| "17".to_string())
- .parse::()
- .map_err(|_| anyhow::anyhow!("Invalid GPIO pin number"))?;
-
- let debounce_delay_secs = std::env::var("NOISEBELL_GPIO_DEBOUNCE_DELAY_SECS")
- .unwrap_or_else(|_| "5".to_string())
- .parse::()
- .map_err(|_| anyhow::anyhow!("Invalid debounce delay"))?;
-
- Ok(Self {
- pin,
- debounce_delay_secs,
- })
- }
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct WebMonitorConfig {
- pub port: u16,
- pub enabled: bool,
-}
-
-impl WebMonitorConfig {
- pub fn from_env() -> Result {
- let port = std::env::var("NOISEBELL_WEB_MONITOR_PORT")
- .unwrap_or_else(|_| "8080".to_string())
- .parse::()
- .map_err(|_| anyhow::anyhow!("Invalid web monitor port"))?;
-
- let enabled = std::env::var("NOISEBELL_WEB_MONITOR_ENABLED")
- .unwrap_or_else(|_| "true".to_string())
- .parse::()
- .map_err(|_| anyhow::anyhow!("Invalid web monitor enabled flag"))?;
-
- Ok(Self {
- port,
- enabled,
- })
- }
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct LoggingConfig {
- pub level: String,
- pub file_path: String,
- pub max_buffered_lines: usize,
-}
-
-impl LoggingConfig {
- pub fn from_env() -> Result {
- let level = std::env::var("NOISEBELL_LOGGING_LEVEL")
- .unwrap_or_else(|_| "info".to_string());
-
- let file_path = std::env::var("NOISEBELL_LOGGING_FILE_PATH")
- .unwrap_or_else(|_| "logs/noisebell.log".to_string());
-
- let max_buffered_lines = std::env::var("NOISEBELL_LOGGING_MAX_BUFFERED_LINES")
- .unwrap_or_else(|_| "10000".to_string())
- .parse::()
- .map_err(|_| anyhow::anyhow!("Invalid max buffered lines"))?;
-
- Ok(Self {
- level,
- file_path,
- max_buffered_lines,
- })
- }
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct MonitorConfig {
- pub monitor_type: String,
-}
-
-impl MonitorConfig {
- pub fn from_env() -> Result {
- let monitor_type = std::env::var("NOISEBELL_MONITOR_TYPE")
- .unwrap_or_else(|_| "web".to_string());
-
- Ok(Self {
- monitor_type,
- })
- }
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct EndpointConfig {
- pub url: String,
- pub api_key: Option,
- pub timeout_secs: u64,
- pub retry_attempts: u32,
-}
-
-impl EndpointConfig {
- pub fn from_env() -> Result {
- let url = std::env::var("NOISEBELL_ENDPOINT_URL")
- .unwrap_or_else(|_| "https://noisebell.jetpham.com/api/status".to_string());
-
- let api_key = std::env::var("ENDPOINT_API_KEY").ok();
-
- let timeout_secs = std::env::var("NOISEBELL_ENDPOINT_TIMEOUT_SECS")
- .unwrap_or_else(|_| "30".to_string())
- .parse::()
- .map_err(|_| anyhow::anyhow!("Invalid endpoint timeout"))?;
-
- let retry_attempts = std::env::var("NOISEBELL_ENDPOINT_RETRY_ATTEMPTS")
- .unwrap_or_else(|_| "3".to_string())
- .parse::()
- .map_err(|_| anyhow::anyhow!("Invalid retry attempts"))?;
-
- Ok(Self {
- url,
- api_key,
- timeout_secs,
- retry_attempts,
- })
- }
-}
-
-impl Config {
- pub fn from_env() -> Result {
- Self::load_env()?;
-
- let config = Config {
- gpio: GpioConfig::from_env()?,
- web_monitor: WebMonitorConfig::from_env()?,
- logging: LoggingConfig::from_env()?,
- monitor: MonitorConfig::from_env()?,
- endpoint: EndpointConfig::from_env()?,
- };
-
- Ok(config)
- }
-
- pub fn load_env() -> Result<()> {
- // Try to load from .env file, but don't fail if it doesn't exist
- match dotenv() {
- Ok(_) => {
- info!("Successfully loaded environment variables from .env file");
- Ok(())
- }
- Err(dotenvy::Error::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
- info!("No .env file found, using system environment variables");
- Ok(())
- }
- Err(e) => {
- Err(anyhow::anyhow!("Failed to load .env file: {}", e))
- }
- }
- }
-
- pub fn validate(&self) -> Result<()> {
- if self.gpio.pin > 40 {
- return Err(anyhow::anyhow!("GPIO pin must be between 1-40"));
- }
-
- if self.gpio.debounce_delay_secs <= 0 {
- return Err(anyhow::anyhow!("Debounce delay must be greater than 0"));
- }
-
- if !["gpio", "web"].contains(&self.monitor.monitor_type.as_str()) {
- return Err(anyhow::anyhow!("Unknown monitor type: {}", self.monitor.monitor_type));
- }
-
- Ok(())
- }
-
- pub fn get_debounce_delay(&self) -> Duration {
- Duration::from_secs(self.gpio.debounce_delay_secs)
- }
-}
\ No newline at end of file
diff --git a/pi/src/endpoint_notifier.rs b/pi/src/endpoint_notifier.rs
deleted file mode 100644
index 8bec149..0000000
--- a/pi/src/endpoint_notifier.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-use serde::{Deserialize, Serialize};
-use serde_json::json;
-use tracing::{info, error, warn};
-use reqwest::Client;
-use tokio::time::{sleep, Duration};
-
-use crate::StatusEvent;
-use anyhow::Result;
-
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct EndpointConfig {
- pub url: String,
- pub api_key: Option,
- pub timeout_secs: u64,
- pub retry_attempts: u32,
-}
-
-pub struct EndpointNotifier {
- config: EndpointConfig,
- client: Client,
-}
-
-impl EndpointNotifier {
- pub fn new(config: EndpointConfig) -> Self {
- let client = Client::builder()
- .timeout(Duration::from_secs(config.timeout_secs))
- .build()
- .expect("Failed to create HTTP client");
-
- Self { config, client }
- }
-
- pub async fn notify_endpoint(&self, event: StatusEvent) -> Result<()> {
- let status = match event {
- StatusEvent::Open => "open",
- StatusEvent::Closed => "closed",
- };
-
- let payload = json!({
- "status": status,
- });
-
- let mut success = false;
- let mut last_error = None;
-
- for attempt in 1..=self.config.retry_attempts {
- match self.send_request(&payload).await {
- Ok(_) => {
- success = true;
- break;
- }
- Err(e) => {
- last_error = Some(e);
- if attempt < self.config.retry_attempts {
- warn!("Attempt {} failed: {}. Retrying...", attempt, last_error.as_ref().unwrap());
- sleep(Duration::from_secs(1)).await;
- }
- }
- }
- }
-
- if !success {
- let error_msg = last_error.unwrap_or_else(|| anyhow::anyhow!("Unknown error"));
- error!("Failed to notify endpoint after {} attempts: {}", self.config.retry_attempts, error_msg);
- return Err(error_msg);
- }
-
- Ok(())
- }
-
- async fn send_request(&self, payload: &serde_json::Value) -> Result<()> {
- let mut request = self.client
- .post(&self.config.url)
- .json(payload);
-
- if let Some(api_key) = &self.config.api_key {
- request = request.header("Authorization", format!("Bearer {}", api_key));
- }
-
- let response = request
- .timeout(Duration::from_secs(self.config.timeout_secs))
- .send()
- .await?;
-
- if !response.status().is_success() {
- return Err(anyhow::anyhow!(
- "HTTP request failed with status {}: {}",
- response.status(),
- response.text().await.unwrap_or_else(|_| "Unknown error".to_string())
- ));
- }
-
- Ok(())
- }
-}
\ No newline at end of file
diff --git a/pi/src/gpio_monitor.rs b/pi/src/gpio_monitor.rs
deleted file mode 100644
index 9ce15af..0000000
--- a/pi/src/gpio_monitor.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-use std::time::Duration;
-use anyhow::{Result, Context};
-use crate::{StatusEvent, monitor::Monitor};
-
-pub struct GpioMonitor {
- pin: rppal::gpio::InputPin,
- debounce_delay: Duration,
-}
-
-impl GpioMonitor {
- pub fn new(pin_number: u8, debounce_delay: Duration) -> Result {
- let gpio = rppal::gpio::Gpio::new().context("Failed to initialize GPIO")?;
- let pin = gpio
- .get(pin_number)
- .context(format!("Failed to get GPIO pin {}", pin_number))?
- .into_input_pullup();
-
- Ok(Self {
- pin,
- debounce_delay,
- })
- }
-}
-
-impl Monitor for GpioMonitor {
- fn monitor(&mut self, mut callback: Box) -> Result<()> {
- self.pin
- .set_async_interrupt(rppal::gpio::Trigger::Both, Some(self.debounce_delay), move |event| {
- match event.trigger {
- rppal::gpio::Trigger::RisingEdge => callback(StatusEvent::Closed),
- rppal::gpio::Trigger::FallingEdge => callback(StatusEvent::Open),
- _ => (), // Ignore other triggers
- }
- })?;
-
- Ok(())
- }
-
- fn get_current_state(&self) -> StatusEvent {
- match self.pin.read() {
- rppal::gpio::Level::Low => StatusEvent::Open,
- rppal::gpio::Level::High => StatusEvent::Closed,
- }
- }
-}
\ No newline at end of file
diff --git a/pi/src/logging.rs b/pi/src/logging.rs
deleted file mode 100644
index f109acc..0000000
--- a/pi/src/logging.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-use std::fs;
-use anyhow::Result;
-use tracing_appender::rolling::RollingFileAppender;
-use tracing_subscriber::filter::LevelFilter;
-use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt};
-use crate::config::LoggingConfig;
-
-pub fn init(config: &LoggingConfig) -> Result<()> {
- tracing::info!("creating logs directory");
- let log_dir = std::path::Path::new(&config.file_path).parent().unwrap_or_else(|| std::path::Path::new("logs"));
- fs::create_dir_all(log_dir)?;
-
- tracing::info!("initializing logging");
- let file_appender = RollingFileAppender::builder()
- .rotation(tracing_appender::rolling::Rotation::NEVER)
- .filename_prefix("noisebell")
- .filename_suffix("log")
- .build(log_dir)?;
-
- let (non_blocking, _guard) = tracing_appender::non_blocking::NonBlockingBuilder::default()
- .buffered_lines_limit(config.max_buffered_lines)
- .finish(file_appender);
-
- // Parse log level from config
- let level_filter = match config.level.to_lowercase().as_str() {
- "trace" => LevelFilter::TRACE,
- "debug" => LevelFilter::DEBUG,
- "info" => LevelFilter::INFO,
- "warn" => LevelFilter::WARN,
- "error" => LevelFilter::ERROR,
- _ => LevelFilter::INFO,
- };
-
- // Only show our logs and hide hyper logs
- let filter = tracing_subscriber::filter::Targets::new()
- .with_target("noisebell", level_filter)
- .with_target("hyper", LevelFilter::WARN)
- .with_target("hyper_util", LevelFilter::WARN);
-
- tracing_subscriber::registry()
- .with(filter)
- .with(fmt::Layer::default().with_writer(std::io::stdout))
- .with(fmt::Layer::default().with_writer(non_blocking))
- .init();
-
- Ok(())
-}
\ No newline at end of file
diff --git a/pi/src/main.rs b/pi/src/main.rs
deleted file mode 100644
index 4bcfe1e..0000000
--- a/pi/src/main.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-mod logging;
-mod monitor;
-mod gpio_monitor;
-mod web_monitor;
-mod endpoint_notifier;
-mod config;
-
-use std::{fmt, sync::Arc};
-use tokio::sync::RwLock;
-
-use anyhow::Result;
-use serde::{Deserialize, Serialize};
-use tracing::{error, info};
-
-// Shared state types
-pub type SharedMonitor = Arc>>;
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
-pub enum StatusEvent {
- Open,
- Closed,
-}
-
-impl fmt::Display for StatusEvent {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- StatusEvent::Open => write!(f, "open"),
- StatusEvent::Closed => write!(f, "closed"),
- }
- }
-}
-
-#[tokio::main]
-async fn main() -> Result<()> {
- // Load and validate configuration
- let config = config::Config::from_env()?;
- config.validate()?;
-
- info!("Configuration loaded successfully");
- info!("Monitor type: {}", config.monitor.monitor_type);
- if config.web_monitor.enabled {
- info!("Web monitor: port {}", config.web_monitor.port);
- }
-
- // Initialize logging with config
- logging::init(&config.logging)?;
-
- // Load endpoint configuration
- info!("Using endpoint URL: {}", config.endpoint.url);
- let endpoint_config = endpoint_notifier::EndpointConfig {
- url: config.endpoint.url.clone(),
- api_key: config.endpoint.api_key.clone(),
- timeout_secs: config.endpoint.timeout_secs,
- retry_attempts: config.endpoint.retry_attempts,
- };
- let notifier = Arc::new(endpoint_notifier::EndpointNotifier::new(endpoint_config));
-
- info!("initializing {} monitor", config.monitor.monitor_type);
- let monitor = monitor::create_monitor(
- &config.monitor.monitor_type,
- config.gpio.pin,
- config.get_debounce_delay(),
- if config.web_monitor.enabled { Some(config.web_monitor.port) } else { None },
- )?;
-
- let shared_monitor: SharedMonitor = Arc::new(RwLock::new(monitor));
-
- let monitor_for_task = shared_monitor.clone();
-
- let callback = {
- let notifier = notifier.clone();
- Box::new(move |event: StatusEvent| {
- let notifier = notifier.clone();
- tokio::spawn(async move {
- if let Err(e) = notifier.notify_endpoint(event).await {
- error!("Failed to notify endpoint: {}", e);
- }
- });
- })
- };
-
- let monitor_handle = tokio::spawn(async move {
- if let Err(e) = monitor_for_task.write().await.monitor(callback) {
- error!("Monitor error: {}", e);
- }
- });
-
- info!("Monitor started with endpoint notifications.");
-
- tokio::select! {
- _ = monitor_handle => {
- info!("Monitor task completed");
- }
- }
-
- info!("Shutting down noisebell...");
- Ok(())
-}
diff --git a/pi/src/monitor.rs b/pi/src/monitor.rs
deleted file mode 100644
index dff8a1a..0000000
--- a/pi/src/monitor.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use std::time::Duration;
-use anyhow::Result;
-use crate::StatusEvent;
-
-pub trait Monitor: Send + Sync {
- fn monitor(&mut self, callback: Box) -> Result<()>;
- fn get_current_state(&self) -> StatusEvent;
-}
-
-pub fn create_monitor(monitor_type: &str, pin_number: u8, debounce_delay: Duration, web_port: Option) -> Result> {
- match monitor_type {
- "gpio" => Ok(Box::new(crate::gpio_monitor::GpioMonitor::new(pin_number, debounce_delay)?)),
- "web" => {
- let port = web_port.ok_or_else(|| anyhow::anyhow!("Web monitor requires a port number"))?;
- Ok(Box::new(crate::web_monitor::WebMonitor::new(port)?))
- },
- _ => Err(anyhow::anyhow!("Unknown monitor type: {}", monitor_type)),
- }
-}
\ No newline at end of file
diff --git a/pi/src/web_monitor.rs b/pi/src/web_monitor.rs
deleted file mode 100644
index edd4d00..0000000
--- a/pi/src/web_monitor.rs
+++ /dev/null
@@ -1,176 +0,0 @@
-use std::sync::Arc;
-use anyhow::Result;
-use axum::{
- extract::{ws::{Message, WebSocket, WebSocketUpgrade}, State},
- response::{Html, IntoResponse},
- routing::{get},
- Router,
-};
-use serde::{Deserialize, Serialize};
-use tokio::sync::{RwLock, Mutex};
-use tracing::{info, error};
-use futures_util::{sink::SinkExt, stream::StreamExt};
-use tower_http::services::ServeDir;
-
-use crate::{StatusEvent, monitor::Monitor};
-
-#[derive(Clone)]
-pub struct WebMonitor {
- port: u16,
- current_state: Arc>,
- callback: Arc>>>,
-}
-
-#[derive(Clone)]
-struct AppState {
- current_state: Arc>,
- callback: Arc>>>,
-}
-
-#[derive(Serialize, Deserialize)]
-struct StateChangeMessage {
- event: String,
- state: String,
-}
-
-impl WebMonitor {
- pub fn new(port: u16) -> Result {
- Ok(Self {
- port,
- current_state: Arc::new(RwLock::new(StatusEvent::Closed)), // Default to closed
- callback: Arc::new(Mutex::new(None)),
- })
- }
-
- async fn serve_html() -> impl IntoResponse {
- Html(include_str!("../static/monitor.html"))
- }
-
- async fn websocket_handler(
- ws: WebSocketUpgrade,
- State(state): State,
- ) -> impl IntoResponse {
- ws.on_upgrade(move |socket| Self::handle_websocket(socket, state))
- }
-
- async fn handle_websocket(socket: WebSocket, state: AppState) {
- let (mut sender, mut receiver) = socket.split();
-
- // Send current state immediately
- let current_state = *state.current_state.read().await;
- let initial_message = StateChangeMessage {
- event: "state_update".to_string(),
- state: current_state.to_string(),
- };
-
- if let Ok(msg) = serde_json::to_string(&initial_message) {
- if let Err(e) = sender.send(Message::Text(msg.into())).await {
- error!("Failed to send initial state: {}", e);
- return;
- }
- }
-
- // Handle incoming messages from client
- let state_for_receiver = state.clone();
- while let Some(msg) = receiver.next().await {
- match msg {
- Ok(Message::Text(text)) => {
- let text_str = text.to_string();
- if let Ok(state_msg) = serde_json::from_str::(&text_str) {
- if state_msg.event == "state_change" {
- let new_state = match state_msg.state.as_str() {
- "open" => StatusEvent::Open,
- "closed" => StatusEvent::Closed,
- _ => continue,
- };
-
- // Update current state
- {
- let mut current = state_for_receiver.current_state.write().await;
- *current = new_state;
- }
-
- // Trigger callback
- {
- let mut callback_guard = state_for_receiver.callback.lock().await;
- if let Some(ref mut callback) = callback_guard.as_mut() {
- callback(new_state);
- }
- }
-
- info!("Web monitor state changed to: {:?}", new_state);
- }
- }
- }
- Ok(Message::Close(_)) => {
- info!("WebSocket connection closed");
- break;
- }
- Err(e) => {
- error!("WebSocket error: {}", e);
- break;
- }
- _ => {}
- }
- }
- }
-
- async fn start_server(&self) -> Result<()> {
- let app_state = AppState {
- current_state: self.current_state.clone(),
- callback: self.callback.clone(),
- };
-
- let app = Router::new()
- .route("/", get(Self::serve_html))
- .route("/ws", get(Self::websocket_handler))
- .nest_service("/media", ServeDir::new("media"))
- .with_state(app_state);
-
- let addr = format!("0.0.0.0:{}", self.port);
- info!("Starting web monitor server on {}", addr);
-
- let listener = tokio::net::TcpListener::bind(&addr).await?;
- axum::serve(listener, app).await?;
-
- Ok(())
- }
-}
-
-impl Monitor for WebMonitor {
- fn monitor(&mut self, callback: Box) -> Result<()> {
- // Store the callback synchronously to ensure it's available immediately
- let callback_arc = self.callback.clone();
- let rt = tokio::runtime::Handle::current();
- tokio::task::block_in_place(|| {
- rt.block_on(async {
- let mut guard = callback_arc.lock().await;
- *guard = Some(callback);
- });
- });
-
- // Run the web server in a blocking task to avoid runtime conflicts
- let server = self.clone();
- tokio::task::spawn_blocking(move || {
- let rt = tokio::runtime::Runtime::new().unwrap();
- if let Err(e) = rt.block_on(server.start_server()) {
- error!("Web monitor server error: {}", e);
- }
- });
-
- loop {
- std::thread::sleep(std::time::Duration::from_secs(1));
- }
- }
-
- fn get_current_state(&self) -> StatusEvent {
- // This is a synchronous function, but we need to read async state
- // We'll use a blocking operation here similar to how GPIO reads work
- let rt = tokio::runtime::Handle::current();
- tokio::task::block_in_place(|| {
- rt.block_on(async {
- *self.current_state.read().await
- })
- })
- }
-}
\ No newline at end of file
diff --git a/pi/static/monitor.html b/pi/static/monitor.html
deleted file mode 100644
index e6dd041..0000000
--- a/pi/static/monitor.html
+++ /dev/null
@@ -1,370 +0,0 @@
-
-
-
-
-
- Circuit Monitor
-
-
-
-
-
-
-
-
-
-
-
-
-
OPEN
-
-
-
-
-
CLOSED
-
-
-
- Connecting...
-
-
-
-
-
-
\ No newline at end of file