exocortex-server 0.4.0

The Exocortex node binary: mcp-standalone and backend-node modes over one listener (gRPC + HTTP + SSE) with gossip and lease re-election.
use std::sync::Arc;

use axum::body::Body;
use axum::http::{Request, StatusCode};
use exocortex_ops::OpContext;
use exocortex_server::http_bind::HttpBind;
use exocortex_server::principal::PrincipalRegistry;
use exocortex_storage::VisibilityContext;
use tower::ServiceExt as _;

const TOKEN: &str = "test-only-audit-bearer-token-00000000";

fn context() -> (Arc<OpContext>, VisibilityContext) {
    let ontology = Arc::new(
        exocortex_kernel::Ontology::from_packs(vec![exocortex_pack_dev_v1::pack_def()]).unwrap(),
    );
    let storage = Arc::new(exocortex_storage::InMemoryStorage::new(ontology));
    let (cache, _writer) = exocortex_cache::LocalCache::new(1024 * 1024);
    let visibility = VisibilityContext {
        user_id: "user".into(),
        org_id: "org".into(),
        project_ids: Default::default(),
        team_ids: Default::default(),
        max_visibility: exocortex_kernel::Visibility::Org,
    };
    (
        Arc::new(OpContext::per_request(
            visibility.clone(),
            storage,
            Arc::new(cache),
            chrono::Duration::seconds(30),
        )),
        visibility,
    )
}

fn audit_request() -> Request<Body> {
    Request::builder()
        .uri("/v1/audit?since_lsn=0")
        .header(axum::http::header::AUTHORIZATION, format!("Bearer {TOKEN}"))
        .body(Body::empty())
        .unwrap()
}

#[tokio::test]
async fn embedded_audit_is_forbidden_by_default_and_explicit_for_admins() {
    let (ctx, visibility) = context();
    let ordinary = HttpBind::new(ctx.clone(), TOKEN.into())
        .router(None)
        .oneshot(audit_request())
        .await
        .unwrap();
    assert_eq!(ordinary.status(), StatusCode::FORBIDDEN);

    let principals = Arc::new(
        PrincipalRegistry::single_with_audit_admin(TOKEN.into(), visibility, true).unwrap(),
    );
    let admin = HttpBind::with_principals(ctx, principals)
        .router(None)
        .oneshot(audit_request())
        .await
        .unwrap();
    assert_eq!(admin.status(), StatusCode::OK);
}

#[cfg(unix)]
#[test]
fn plaintext_principal_policy_must_be_owner_only_before_parsing() {
    use std::os::unix::fs::PermissionsExt as _;

    let dir = tempfile::tempdir().unwrap();
    let path = dir.path().join("principals.json");
    std::fs::write(&path, "not-json").unwrap();
    std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o640)).unwrap();
    let error = PrincipalRegistry::load(&path).err().unwrap().to_string();
    assert!(error.contains("owner-only"), "{error}");

    std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o600)).unwrap();
    let error = PrincipalRegistry::load(&path).err().unwrap().to_string();
    assert!(error.contains("parse principal policy"), "{error}");
}