agent-infra-sdk 0.1.1

Gateway-backed Rust SDK for Agent Infra APIs
Documentation
//! Typed control/data-plane client for Runtime Workload Identity.

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 {
    /// Internal Gateway upstream constructor. Application developers should
    /// obtain this client from [`crate::InfraClient::runtime_identity`].
    #[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
    }
}