Commit f6d165c
committed
chore(release): 2.0.0 [skip ci]
# [2.0.0](v1.2.0...v2.0.0) (2026-02-18)
### Features
* **auth:** replace static hotkey/API-key auth with Bittensor validator whitelisting and 50% consensus ([#5](#5)) ([a573ad0](a573ad0))
### BREAKING CHANGES
* **auth:** WORKER_API_KEY env var and X-Api-Key header no longer required.
All validators on Bittensor netuid 100 with sufficient stake are auto-whitelisted.
* ci: trigger CI run
* fix(security): address auth bypass, input validation, and config issues
- Move nonce consumption AFTER signature verification in verify_request()
to prevent attackers from burning legitimate nonces via invalid signatures
- Fix TOCTOU race in NonceStore::check_and_insert() using atomic DashMap
entry API instead of separate contains_key + insert
- Add input length limits for auth headers (hotkey 128B, nonce 256B,
signature 256B) to prevent memory exhaustion via oversized values
- Add consensus_threshold validation in Config::from_env() — must be
in range (0.0, 1.0], panics at startup if invalid
- Add saturating conversion for consensus required calculation to prevent
integer overflow on f64→usize cast
- Add tests for all security fixes
* fix(dead-code): remove orphaned default_concurrent fn and unnecessary allow(dead_code)
* fix: code quality issues in bittensor validator consensus
- Extract magic number 100 to configurable MAX_PENDING_CONSENSUS
- Restore #[allow(dead_code)] on DEFAULT_MAX_OUTPUT_BYTES constant
- Use anyhow::Context instead of map_err(anyhow::anyhow!) in validator_whitelist
* fix(security): address race condition, config panic, SS58 checksum, and container security
- consensus.rs: Fix TOCTOU race condition in record_vote by using
DashMap entry API (remove_entry) to atomically check votes and remove
entry while holding the shard lock, preventing concurrent threads from
inserting votes between drop and remove
- config.rs: Replace assert! with proper Result<Self, String> return
from Config::from_env() to avoid panicking in production on invalid
CONSENSUS_THRESHOLD values
- main.rs: Update Config::from_env() call to handle Result with expect
- auth.rs: Add SS58 checksum verification using Blake2b-512 (correct
Substrate algorithm) in ss58_to_public_key_bytes to reject addresses
with corrupted checksums; previously only decoded base58 without
validating the 2-byte checksum suffix
- Dockerfile: Add non-root executor user for container runtime security
* fix(dead-code): remove unused max_output_bytes config field and constant
Remove DEFAULT_MAX_OUTPUT_BYTES constant and max_output_bytes Config field
that were defined and populated from env but never read anywhere outside
config.rs. Both had #[allow(dead_code)] annotations suppressing warnings.
* fix(quality): replace expect/unwrap with proper error handling, extract magic numbers to constants
- main.rs: Replace .expect() on Config::from_env() with match + tracing::error! + process::exit(1)
- validator_whitelist.rs: Extract retry count (3) and backoff base (2) to named constants
- validator_whitelist.rs: Replace unwrap_or_else on Option with if-let pattern
- consensus.rs: Extract reaper interval (30s) to REAPER_INTERVAL_SECS constant
* fix(security): address multiple security vulnerabilities in PR files
- consensus.rs: Remove archive_data storage from PendingConsensus to
prevent memory exhaustion (up to 50GB with 100 pending × 500MB each).
Callers now use their own archive bytes since all votes for the same
hash have identical data.
- handlers.rs: Stream multipart upload with per-chunk size enforcement
instead of buffering entire archive before checking size limit.
Sanitize error messages to not leak internal details (file paths,
extraction errors) to clients; log details server-side instead.
- auth.rs: Add nonce format validation requiring non-empty printable
ASCII characters (defense-in-depth against log injection and empty
nonce edge cases).
- main.rs: Replace .unwrap() on TcpListener::bind and axum::serve with
proper error logging and process::exit per AGENTS.md rules.
- ws.rs: Replace .unwrap() on serde_json::to_string with
unwrap_or_default() to comply with AGENTS.md no-unwrap rule.
* fix(dead-code): rename misleading underscore-prefixed variable in consensus
* fix(quality): replace unwrap/expect with proper error handling in production code
- main.rs:21: Replace .parse().unwrap() on tracing directive with
unwrap_or_else fallback to INFO level directive
- main.rs:36: Replace .expect() on workspace dir creation with
error log + process::exit(1) pattern
- main.rs:110: Replace .expect() on ctrl_c handler with if-let-Err
that logs and returns gracefully
- executor.rs:189: Replace semaphore.acquire().unwrap() with match
that handles closed semaphore by creating a failed TaskResult
All changes follow AGENTS.md rule: no .unwrap()/.expect() in
production code paths. Test code is unchanged.
* docs: refresh AGENTS.md1 parent a573ad0 commit f6d165c
3 files changed
+108
-2
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
1 | 107 | | |
2 | 108 | | |
3 | 109 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
0 commit comments