Menu
Public repository / master
AkurAI-Drive / contracts/src/lib.rs
Latest change 54e252bb8ef81aab2ef9033bff0874b8afe40922 - refactor(drive): share versioned API contracts by AkurAI Agent
//! Versioned JSON wire types shared by the Drive API and native clients.
//!
//! `created` is always Unix seconds, matching the SQLite storage schema.
use serde::{Deserialize, Serialize};
pub const API_VERSION: &str = "v1";
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Bucket {
pub bucket: String,
#[serde(default)]
pub region: String,
#[serde(default)]
pub plan: String,
#[serde(default)]
pub org: String,
#[serde(default)]
pub created: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct StorageBucket {
pub id: String,
pub org: String,
pub plan: String,
pub bucket: String,
pub region: String,
pub created: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct RemoteFile {
pub key: String,
#[serde(default)]
pub size: u64,
#[serde(default)]
pub etag: String,
#[serde(default)]
pub last_modified: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Presign {
pub url: String,
pub method: String,
#[serde(default)]
pub expires_in: u64,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
pub struct Identity {
#[serde(default)]
pub authenticated: bool,
#[serde(default)]
pub sub: String,
#[serde(default)]
pub email: String,
#[serde(default)]
pub groups: Vec<String>,
#[serde(default)]
pub is_admin: bool,
#[serde(default)]
pub tenant_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct BucketsResponse {
pub buckets: Vec<Bucket>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct StorageResponse {
pub buckets: Vec<StorageBucket>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct FilesResponse {
pub files: Vec<RemoteFile>,
}
#[cfg(test)]
mod tests {
use super::{Bucket, BucketsResponse};
#[test]
fn bucket_fixture_round_trips_unix_seconds() {
let fixture = r#"{"buckets":[{"bucket":"drive-acme","region":"eu-west-1","plan":"pro","org":"Acme ehf.","created":1700000000}]}"#;
let response: BucketsResponse = serde_json::from_str(fixture).expect("bucket fixture");
assert_eq!(response.buckets[0].created, 1_700_000_000);
assert_eq!(
serde_json::to_value(&response.buckets[0]).unwrap()["created"],
1_700_000_000
);
}
#[test]
fn bucket_defaults_missing_optional_fields() {
let bucket: Bucket = serde_json::from_str(r#"{"bucket":"drive-acme"}"#).unwrap();
assert_eq!(bucket.created, 0);
assert!(bucket.region.is_empty());
}
}