use agent_runtime_identity_contract::{
CreateRuntimeIdentityRequest, CreateRuntimeIdentityResponse, IDENTITIES_PATH, IDENTITY_PATH,
ISSUE_CREDENTIAL_PATH, IssueRuntimeCredentialRequest, IssueRuntimeCredentialResponse,
LIST_IDENTITIES_PATH, ListRuntimeIdentitiesRequest, PERMISSIONS_PATH, PermissionsResponse,
REVOKE_CREDENTIAL_PATH, ReplacePermissionsRequest, RevokeRuntimeCredentialRequest,
RuntimeIdentity, RuntimeIdentityId, SERVICE_NAME, TransitionIdentityRequest,
VERIFY_CREDENTIAL_PATH, VerifyRuntimeCredentialRequest, VerifyRuntimeCredentialResponse,
};
use reqwest::Client;
use crate::transport::{
CallOptions, ClientOptions, HttpTransport, InfraClientError, ServiceEndpoint,
};
#[derive(Clone, Debug)]
pub struct RuntimeIdentityClient {
transport: HttpTransport,
}
impl RuntimeIdentityClient {
#[doc(hidden)]
pub fn new_for_gateway_upstream(http: Client, base_url: impl Into<String>) -> Self {
Self::new_with_endpoint(
http,
ServiceEndpoint::new(base_url),
ClientOptions::default(),
)
}
pub(crate) fn new_with_endpoint(
http: Client,
endpoint: ServiceEndpoint,
options: ClientOptions,
) -> Self {
let endpoint = endpoint.with_default_credential_audience("agent-runtime-identity-admin");
Self {
transport: HttpTransport::new_with_options(http, SERVICE_NAME, endpoint, options),
}
}
pub async fn create(
&self,
request: &CreateRuntimeIdentityRequest,
) -> Result<CreateRuntimeIdentityResponse, InfraClientError> {
self.transport.post_json(IDENTITIES_PATH, request).await
}
pub async fn get(
&self,
identity_id: &RuntimeIdentityId,
) -> Result<RuntimeIdentity, InfraClientError> {
self.transport
.get_json(&IDENTITY_PATH.replace("{identity_id}", identity_id.as_str()))
.await
}
pub async fn list(
&self,
request: &ListRuntimeIdentitiesRequest,
) -> Result<Vec<RuntimeIdentity>, InfraClientError> {
self.transport
.post_json(LIST_IDENTITIES_PATH, request)
.await
}
pub async fn transition(
&self,
identity_id: &RuntimeIdentityId,
action: &str,
request: &TransitionIdentityRequest,
) -> Result<RuntimeIdentity, InfraClientError> {
if !matches!(action, "activate" | "suspend" | "resume" | "revoke") {
return Err(InfraClientError::Protocol {
service: SERVICE_NAME,
message: "unknown runtime identity transition".into(),
});
}
let path = format!(
"{}:{action}",
IDENTITY_PATH.replace("{identity_id}", identity_id.as_str())
);
self.transport.post_json(&path, request).await
}
pub async fn replace_permissions(
&self,
identity_id: &RuntimeIdentityId,
request: &ReplacePermissionsRequest,
) -> Result<PermissionsResponse, InfraClientError> {
self.transport
.put_json_with_options(
&PERMISSIONS_PATH.replace("{identity_id}", identity_id.as_str()),
request,
CallOptions::default().idempotent(true),
)
.await
}
pub async fn issue_credential(
&self,
request: &IssueRuntimeCredentialRequest,
) -> Result<IssueRuntimeCredentialResponse, InfraClientError> {
self.transport
.post_json(ISSUE_CREDENTIAL_PATH, request)
.await
}
pub async fn verify_credential(
&self,
request: &VerifyRuntimeCredentialRequest,
) -> Result<VerifyRuntimeCredentialResponse, InfraClientError> {
self.transport
.post_json(VERIFY_CREDENTIAL_PATH, request)
.await
}
pub async fn revoke_credential(
&self,
request: &RevokeRuntimeCredentialRequest,
) -> Result<(), InfraClientError> {
self.transport
.post_json(REVOKE_CREDENTIAL_PATH, request)
.await
}
}