From 72138069dde24a998e03b073d3fc40ce1c085d81 Mon Sep 17 00:00:00 2001 From: Zachery Aaron Shores-Chmielewski Date: Sun, 15 Feb 2026 21:35:10 +0700 Subject: [PATCH] fix: adjust auth protocol to datastore protocol --- crates/datastore/src/messages.rs | 1 + crates/distribution/src/auth.rs | 145 ------------------------------ crates/distribution/src/crypto.rs | 16 ---- crates/distribution/src/lib.rs | 1 - 4 files changed, 1 insertion(+), 162 deletions(-) delete mode 100644 crates/distribution/src/auth.rs diff --git a/crates/datastore/src/messages.rs b/crates/datastore/src/messages.rs index fd5f8ae..92d0d4b 100644 --- a/crates/datastore/src/messages.rs +++ b/crates/datastore/src/messages.rs @@ -460,3 +460,4 @@ pub enum GatewayMsg { /// Periodic nonce garbage collection tick. NonceGcTick, } + diff --git a/crates/distribution/src/auth.rs b/crates/distribution/src/auth.rs deleted file mode 100644 index 46a7ba3..0000000 --- a/crates/distribution/src/auth.rs +++ /dev/null @@ -1,145 +0,0 @@ -use std::collections::HashSet; -use std::fmt; - -use serde::{Deserialize, Serialize}; - -use crate::types::{NodeId, Signature}; - -// ─── ContentHash ──────────────────────────────────────────────────────────── - -/// A 32-byte blake3 digest used as content address for chunks and manifests. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct ContentHash(pub [u8; 32]); - -impl fmt::Debug for ContentHash { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ContentHash(")?; - for b in &self.0[..4] { - write!(f, "{:02x}", b)?; - } - write!(f, "\u{2026})") - } -} - -// ─── DatastoreAction ──────────────────────────────────────────────────────── - -/// An action a client wants to perform on the datastore. -/// -/// Carried inside a `SignedRequestPayload` for browser-relay auth (Auth Path 2). -#[derive(Debug, Clone, Serialize, Deserialize)] -pub enum DatastoreAction { - Put { - path: String, - content_hash: ContentHash, - size_bytes: u64, - tags: std::collections::BTreeMap, - }, - Get { - path: String, - }, - Delete { - path: String, - }, - List { - prefix: Option, - }, -} - -// ─── SignedRequestPayload ─────────────────────────────────────────────────── - -/// The signable payload of a client request. -/// -/// Serialized canonically (serde_json) and signed by the client's ed25519 key. -/// Includes timestamp and nonce for replay protection. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SignedRequestPayload { - pub action: DatastoreAction, - /// Unix timestamp in seconds. - pub timestamp: u64, - /// 16 random bytes — prevents replay within the timestamp window. - pub nonce: [u8; 16], -} - -// ─── SignedRequest ────────────────────────────────────────────────────────── - -/// A signed request envelope for browser-relay auth (Auth Path 2). -/// -/// The relay forwards this opaquely — it cannot forge, modify, or replay it. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SignedRequest { - pub payload: SignedRequestPayload, - /// The client's ed25519 public key. - pub public_key: NodeId, - /// ed25519 signature over the canonical serialization of `payload`. - pub signature: Signature, -} - -// ─── AccessControlList ────────────────────────────────────────────────────── - -/// The datastore's access control list. -/// -/// Persisted as `acl.json` alongside the datastore's `storage_path`. -/// The owner always has implicit full access. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AccessControlList { - /// The datastore owner's public key — always has full access. - pub owner: NodeId, - /// Explicitly authorized client keys. - pub authorized_keys: HashSet, -} - -// ─── AuthzResult ──────────────────────────────────────────────────────────── - -/// The outcome of an authorization check. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum AuthzResult { - Allowed, - Denied(DeniedReason), -} - -/// Why a request was denied. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum DeniedReason { - /// The key is not in the ACL. - NotAuthorized, - /// The ed25519 signature is invalid. - InvalidSignature, - /// The request timestamp is outside the ±300s window. - RequestExpired, - /// The nonce has already been seen within the time window. - ReplayDetected, -} - -// ─── AuthzEngine ──────────────────────────────────────────────────────────── - -/// Authorization engine — checks requests against the ACL and replay state. -/// -/// Sits at the edge of the actor system (Auth Gate) and decides whether -/// to accept or reject external requests before they reach the actors. -#[derive(Debug)] -pub struct AuthzEngine { - pub acl: AccessControlList, - // Nonce tracking and other runtime state will be added during implementation. -} - -impl AuthzEngine { - /// Check whether a `NodeId` is authorized (connection-level, Auth Path 1). - pub fn check_node(&self, _node_id: &NodeId) -> AuthzResult { - todo!() - } - - /// Verify and authorize a signed request (Auth Path 2). - pub fn check_signed_request(&self, _request: &SignedRequest) -> AuthzResult { - todo!() - } - - /// Grant access to a `NodeId`. Owner-only operation. - pub fn grant(&mut self, _requester: &NodeId, _key: NodeId) -> Result<(), DeniedReason> { - todo!() - } - - /// Revoke access from a `NodeId`. Owner-only operation. - pub fn revoke(&mut self, _requester: &NodeId, _key: NodeId) -> Result<(), DeniedReason> { - todo!() - } -} diff --git a/crates/distribution/src/crypto.rs b/crates/distribution/src/crypto.rs index 2c781b2..43a1a42 100644 --- a/crates/distribution/src/crypto.rs +++ b/crates/distribution/src/crypto.rs @@ -1,6 +1,5 @@ use ed25519_dalek::{Signer, Verifier}; -use crate::auth::{SignedRequest, SignedRequestPayload}; use crate::types::{DirectoryEntry, DirectoryEntryPayload, NodeId, Signature}; // ─── Keypair ──────────────────────────────────────────────────────────────── @@ -42,13 +41,6 @@ impl Keypair { Signature(sig.to_bytes()) } - /// Sign a request payload, returning a complete `SignedRequest` envelope. - /// - /// Used by clients for Auth Path 2 (browser relay). - pub fn sign_request(&self, _payload: &SignedRequestPayload) -> SignedRequest { - todo!() - } - /// Sign a directory entry payload, returning a complete `DirectoryEntry`. pub fn sign_directory_entry( &self, @@ -82,14 +74,6 @@ pub fn verify(node_id: &NodeId, msg: &[u8], sig: &Signature) -> bool { vk.verify(msg, &signature).is_ok() } -/// Verify a `SignedRequest`'s signature against its embedded `public_key`. -/// -/// Checks only signature validity — does NOT check timestamp, nonce, or ACL. -/// Use `AuthzEngine::check_signed_request` for full verification. -pub fn verify_signed_request(_request: &SignedRequest) -> bool { - todo!() -} - /// Verify a `DirectoryEntry`'s signature against its embedded `node_id`. pub fn verify_directory_entry(entry: &DirectoryEntry) -> bool { let payload = entry.payload(); diff --git a/crates/distribution/src/lib.rs b/crates/distribution/src/lib.rs index 3df3e92..503bbf0 100644 --- a/crates/distribution/src/lib.rs +++ b/crates/distribution/src/lib.rs @@ -14,4 +14,3 @@ pub mod snapshot; pub mod driver; #[cfg(feature = "iroh")] pub mod iroh_driver; -pub mod auth;