api: expose community edition capabilities

This commit is contained in:
a.tolmachev
2026-05-03 15:49:07 +00:00
parent 6fd62df2a8
commit d98aa83b37
12 changed files with 215 additions and 10 deletions
+39
View File
@@ -23,6 +23,7 @@ use crate::{
update_profile,
},
auth_profiles::{create_auth_profile, get_auth_profile, list_auth_profiles},
capabilities::get_capabilities,
observability::{get_agent_usage, get_log, get_operation_usage, get_usage, list_logs},
operations::{
archive_operation, create_operation, create_version, delete_operation,
@@ -167,6 +168,7 @@ pub fn build_app(state: AppState) -> Router {
.route("/async-jobs/{job_id}/result", get(get_async_job_result));
let workspace_root_router = Router::new()
.route("/capabilities", get(get_capabilities))
.route("/workspaces", get(list_workspaces).post(create_workspace))
.layer(middleware::from_fn_with_state(
state.clone(),
@@ -999,6 +1001,43 @@ mod tests {
assert_eq!(delete_status, reqwest::StatusCode::NO_CONTENT);
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn returns_community_capabilities() {
let registry = test_registry().await;
let storage_root = test_storage_root("community_capabilities");
let base_url = spawn_admin_api(build_test_app(registry, storage_root)).await;
let client = authorized_client(&base_url).await;
let root_url = base_url
.as_ref()
.split("/api/admin/workspaces/")
.next()
.unwrap();
let response = assert_success_json(
client
.get(format!("{root_url}/api/admin/capabilities"))
.send()
.await
.unwrap(),
)
.await;
assert_eq!(response["edition"], "community");
assert_eq!(
response["supported_protocols"],
json!(["rest", "graphql", "grpc"])
);
assert_eq!(response["supported_security_levels"], json!(["standard"]));
assert_eq!(
response["machine_access_modes"],
json!(["static_agent_key"])
);
assert_eq!(response["limits"]["max_workspaces"], 1);
assert_eq!(response["limits"]["max_users_per_workspace"], 1);
assert_eq!(response["limits"]["max_agents_per_workspace"], 1);
}
#[tokio::test(flavor = "multi_thread")]
#[serial]
async fn manages_workspace_access_lifecycle() {
+1
View File
@@ -2,6 +2,7 @@ pub mod access;
pub mod agents;
pub mod auth;
pub mod auth_profiles;
pub mod capabilities;
pub mod observability;
pub mod operations;
pub mod secrets;
@@ -0,0 +1,8 @@
use axum::{Json, extract::State};
use serde_json::json;
use crate::state::AppState;
pub async fn get_capabilities(State(state): State<AppState>) -> Json<serde_json::Value> {
Json(json!(state.service.get_capabilities().await))
}
+23 -7
View File
@@ -9,13 +9,15 @@ use crank_adapter_grpc::test_support as grpc_test_support;
use crank_adapter_soap::{SoapServiceSummary, inspect_wsdl};
use crank_core::{
Agent, AgentId, AgentOperationBinding, AgentStatus, AgentVersion, AggregationMode,
AsyncJobHandle, AuthConfig, AuthKind, AuthProfile, AuthProfileId, ConfigExport, ExecutionMode,
ExportMode, GeneratedDraft, GeneratedDraftStatus, InvitationId, InvitationStatus,
InvitationToken, InvocationLevel, InvocationLog, InvocationLogId, InvocationSource,
InvocationStatus, JobStatus, MembershipRole, OperationId, OperationStatus, PlatformApiKey,
PlatformApiKeyId, PlatformApiKeyScope, PlatformApiKeyStatus, Protocol, SampleId, Samples,
Secret, SecretId, SecretKind, SecretStatus, StreamSession, StreamStatus, Target,
TransportBehavior, UsagePeriod, UserId, UserSessionId, Workspace, WorkspaceId, WorkspaceStatus,
AsyncJobHandle, AuthConfig, AuthKind, AuthProfile, AuthProfileId, ConfigExport,
EditionCapabilities, EditionLimits, ExecutionMode, ExportMode, GeneratedDraft,
GeneratedDraftStatus, InvitationId, InvitationStatus, InvitationToken, InvocationLevel,
InvocationLog, InvocationLogId, InvocationSource, InvocationStatus, JobStatus,
MachineAccessMode, MembershipRole, OperationId, OperationSecurityLevel, OperationStatus,
PlatformApiKey, PlatformApiKeyId, PlatformApiKeyScope, PlatformApiKeyStatus, ProductEdition,
Protocol, SampleId, Samples, Secret, SecretId, SecretKind, SecretStatus, StreamSession,
StreamStatus, Target, TransportBehavior, UsagePeriod, UserId, UserSessionId, Workspace,
WorkspaceId, WorkspaceStatus,
};
use crank_mapping::{JsonPathRoot, MappingSet, infer_mapping_from_samples};
use crank_proto::{ProtoService, services_from_descriptor_set_bytes};
@@ -1566,6 +1568,20 @@ impl AdminService {
.collect()
}
pub async fn get_capabilities(&self) -> EditionCapabilities {
EditionCapabilities {
edition: ProductEdition::Community,
supported_protocols: vec![Protocol::Rest, Protocol::Graphql, Protocol::Grpc],
supported_security_levels: vec![OperationSecurityLevel::Standard],
machine_access_modes: vec![MachineAccessMode::StaticAgentKey],
limits: EditionLimits {
max_workspaces: Some(1),
max_users_per_workspace: Some(1),
max_agents_per_workspace: Some(1),
},
}
}
#[instrument(skip(self))]
pub async fn list_stream_sessions(
&self,