Update archipelago: API, auth, container, parmanode, performance, security

- API handler, RPC, and server updates
- Auth and coding rules
- Container data manager, dev orchestrator, health monitor, podman client
- Parmanode script runner
- Performance resource manager
- Security container policies and secrets manager
- Add build scripts and documentation
This commit is contained in:
Dorian
2026-01-27 22:27:17 +00:00
parent 0d073fa89e
commit 1c024c5d64
5332 changed files with 8978 additions and 24160 deletions
+11 -16
View File
@@ -1,15 +1,12 @@
use crate::api::rpc::RpcHandler;
use crate::config::Config;
use anyhow::Result;
use http_body_util::{BodyExt, Full};
use hyper::body::Bytes;
use hyper::{Method, Request, Response, StatusCode};
use hyper_util::rt::TokioIo;
use std::sync::Arc;
use tracing::debug;
pub struct ApiHandler {
config: Config,
_config: Config,
rpc_handler: Arc<RpcHandler>,
// Add other handlers here (websocket, static files, etc.)
}
@@ -19,28 +16,26 @@ impl ApiHandler {
let rpc_handler = Arc::new(RpcHandler::new(config.clone()).await?);
Ok(Self {
config,
_config: config,
rpc_handler,
})
}
pub async fn handle_request(
&self,
req: Request<http_body_util::Incoming>,
) -> Result<Response<Full<Bytes>>> {
req: Request<hyper::Body>,
) -> Result<Response<hyper::Body>> {
// Extract path and method before consuming req
let path = req.uri().path().to_string();
let method = req.method().clone();
// Convert body to bytes using http_body_util::BodyExt
// Convert body to bytes
let (parts, body) = req.into_parts();
use http_body_util::BodyExt;
let collected: http_body_util::Collected<Bytes> = body.collect().await
.map_err(|_e| anyhow::anyhow!("Failed to read body"))?;
let body_bytes = collected.to_bytes();
let body_bytes = hyper::body::to_bytes(body).await
.map_err(|e| anyhow::anyhow!("Failed to read body: {}", e))?;
// Reconstruct request with Full<Bytes> body for RPC handler
let req_with_bytes = Request::from_parts(parts, Full::new(body_bytes));
// Reconstruct request with body as Bytes for RPC handler
let req_with_bytes = Request::from_parts(parts, hyper::Body::from(body_bytes));
debug!("{} {}", method, path);
@@ -52,13 +47,13 @@ impl ApiHandler {
(Method::GET, "/health") => {
Ok(Response::builder()
.status(StatusCode::OK)
.body(Full::new(Bytes::from("OK")))
.body(hyper::Body::from("OK"))
.unwrap())
}
_ => {
Ok(Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Full::new(Bytes::from("Not Found")))
.body(hyper::Body::from("Not Found"))
.unwrap())
}
}
-1
View File
@@ -2,4 +2,3 @@ mod handler;
mod rpc;
pub use handler::ApiHandler;
pub use rpc::RpcHandler;
+8 -14
View File
@@ -1,12 +1,9 @@
use crate::config::Config;
use crate::container::DevContainerOrchestrator;
use anyhow::{Context, Result};
use http_body_util::{BodyExt, Full};
use hyper::body::Bytes;
use hyper::{Request, Response, StatusCode};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::{debug, error};
#[derive(Debug, Deserialize)]
@@ -29,7 +26,7 @@ struct RpcError {
}
pub struct RpcHandler {
config: Config,
_config: Config,
orchestrator: Option<Arc<DevContainerOrchestrator>>,
}
@@ -44,22 +41,19 @@ impl RpcHandler {
};
Ok(Self {
config,
_config: config,
orchestrator,
})
}
pub async fn handle(
&self,
req: Request<Full<Bytes>>,
) -> Result<Response<Full<Bytes>>> {
// Read request body - Full<Bytes> is already collected
req: Request<hyper::Body>,
) -> Result<Response<hyper::Body>> {
// Read request body
let (_, body) = req.into_parts();
// Full<Bytes> implements Body, collect it to get the bytes
use http_body_util::BodyExt;
let collected = body.collect().await
.context("Failed to collect body")?;
let body_bytes = collected.to_bytes();
let body_bytes = hyper::body::to_bytes(body).await
.context("Failed to read body")?;
let rpc_req: RpcRequest = serde_json::from_slice(&body_bytes)
.context("Invalid RPC request")?;
@@ -108,7 +102,7 @@ impl RpcHandler {
Ok(Response::builder()
.status(StatusCode::OK)
.header("Content-Type", "application/json")
.body(Full::new(Bytes::from(body)))
.body(hyper::Body::from(body))
.unwrap())
}
+3
View File
@@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use tokio::fs;
#[allow(dead_code)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
pub password_hash: String,
@@ -13,10 +14,12 @@ pub struct User {
pub onboarding_complete: bool,
}
#[allow(dead_code)]
pub struct AuthManager {
data_dir: PathBuf,
}
#[allow(dead_code)]
impl AuthManager {
pub fn new(data_dir: PathBuf) -> Self {
Self { data_dir }
@@ -1,5 +1,5 @@
use anyhow::{Context, Result};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use tokio::fs;
pub struct DevDataManager {
@@ -66,6 +66,7 @@ impl DevDataManager {
}
/// Get all app data directories
#[allow(dead_code)]
pub async fn list_app_data_dirs(&self) -> Result<Vec<String>> {
if !self.dev_data_dir.exists() {
return Ok(vec![]);
@@ -3,9 +3,7 @@ use archipelago_container::{
ContainerStatus, PortManager,
};
use anyhow::{Context, Result};
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::RwLock;
use crate::config::{Config, ContainerRuntime, BitcoinSimulation};
use crate::container::data_manager::DevDataManager;
@@ -65,7 +63,7 @@ impl DevContainerOrchestrator {
pub async fn install_container(
&self,
manifest: &AppManifest,
manifest_path: &str,
_manifest_path: &str,
) -> Result<String> {
let app_id = &manifest.app.id;
let container_name = format!("archipelago-{}-dev", app_id);
@@ -251,11 +249,13 @@ impl DevContainerOrchestrator {
}
/// Get port mapping for an app
#[allow(dead_code)]
pub fn get_port_mapping(&self, app_id: &str) -> Option<Vec<u16>> {
self.port_manager.get_port_mapping(app_id)
}
/// Get Bitcoin simulator
#[allow(dead_code)]
pub fn bitcoin_simulator(&self) -> &Arc<BitcoinSimulator> {
&self.bitcoin_simulator
}
-1
View File
@@ -1,5 +1,4 @@
pub mod data_manager;
pub mod dev_orchestrator;
pub use data_manager::DevDataManager;
pub use dev_orchestrator::DevContainerOrchestrator;
+1 -1
View File
@@ -3,7 +3,7 @@
use anyhow::Result;
use std::net::SocketAddr;
use tracing::{info, error};
use tracing::info;
mod api;
mod auth;
+7 -15
View File
@@ -1,16 +1,15 @@
use crate::api::ApiHandler;
use crate::config::Config;
use anyhow::Result;
use hyper_util::rt::TokioIo;
use hyper_util::server::conn::auto::Builder as AutoBuilder;
use hyper::server::conn::Http;
use hyper::service::service_fn;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::net::TcpListener;
use hyper::service::service_fn;
use tracing::{error, info};
use tracing::error;
pub struct Server {
config: Config,
_config: Config,
api_handler: Arc<ApiHandler>,
}
@@ -19,7 +18,7 @@ impl Server {
let api_handler = Arc::new(ApiHandler::new(config.clone()).await?);
Ok(Self {
config,
_config: config,
api_handler,
})
}
@@ -36,7 +35,6 @@ impl Server {
}
};
let io = TokioIo::new(stream);
let handler = self.api_handler.clone();
tokio::spawn(async move {
@@ -48,14 +46,8 @@ impl Server {
}
});
let mut builder = AutoBuilder::new(
hyper_util::rt::TokioExecutor::new()
);
// Use HTTP/1.1 only for now
builder = builder.http1_only();
if let Err(e) = builder
.serve_connection(io, service)
if let Err(e) = Http::new()
.serve_connection(stream, service)
.await
{
error!("Error serving connection from {}: {}", peer_addr, e);