Expose approval requests in admin logs
This commit is contained in:
@@ -28,10 +28,10 @@ pub mod requests {
|
||||
CreatePlatformApiKeyRequest, CreateSecretRequest, CreateVersionRequest,
|
||||
CreateWorkspaceRequest, CreateYamlImportJobRequest, DecideApprovalRequest,
|
||||
ExpireApprovalRequest, FinishApprovalRequest, FinishImportJobRequest,
|
||||
ListInvocationLogsQuery, PublishAgentRequest, PublishRequest, RotateSecretRequest,
|
||||
SaveAgentBindingsRequest, SaveAuthProfileRequest, SaveDescriptorMetadataRequest,
|
||||
SaveSampleMetadataRequest, SaveWorkspaceUpstreamRequest, UpdateWorkspaceRequest,
|
||||
UsageQuery,
|
||||
ListApprovalRequestsQuery, ListInvocationLogsQuery, PublishAgentRequest, PublishRequest,
|
||||
RotateSecretRequest, SaveAgentBindingsRequest, SaveAuthProfileRequest,
|
||||
SaveDescriptorMetadataRequest, SaveSampleMetadataRequest, SaveWorkspaceUpstreamRequest,
|
||||
UpdateWorkspaceRequest, UsageQuery,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -47,15 +47,16 @@ pub use model::{
|
||||
CreatePlatformApiKeyRequest, CreateSecretRequest, CreateVersionRequest, CreateWorkspaceRequest,
|
||||
CreateYamlImportJobRequest, DecideApprovalRequest, DescriptorKind, DescriptorMetadata,
|
||||
ExpireApprovalRequest, FinishApprovalRequest, FinishImportJobRequest, ImportJob, ImportJobId,
|
||||
ImportJobKind, ImportJobStatus, InvitationRecord, InvocationLogRecord, ListInvocationLogsQuery,
|
||||
MembershipRecord, OperationAgentRef, OperationSampleMetadata, OperationSummary,
|
||||
OperationUsageSummary, OperationVersionRecord, Page, PlatformApiKeyRecord, PublishAgentRequest,
|
||||
PublishRequest, PublishedAgentTool, RegistryOperation, RotateSecretRequest, SampleKind,
|
||||
SaveAgentBindingsRequest, SaveAuthProfileRequest, SaveDescriptorMetadataRequest,
|
||||
SaveSampleMetadataRequest, SaveWorkspaceUpstreamRequest, SecretRecord, SecretVersionRecord,
|
||||
SessionRecord, UpdateWorkspaceRequest, UsageAgentBreakdown, UsageBucket,
|
||||
UsageOperationBreakdown, UsageQuery, UsageRollupRecord, UsageSummary, UsageTimelinePoint,
|
||||
WorkspaceMembershipRecord, WorkspaceRecord, WorkspaceUpstream, WorkspaceUpstreamId,
|
||||
YamlImportJob, YamlImportJobCompletion, YamlImportJobId, YamlImportJobStatus,
|
||||
ImportJobKind, ImportJobStatus, InvitationRecord, InvocationLogRecord,
|
||||
ListApprovalRequestsQuery, ListInvocationLogsQuery, MembershipRecord, OperationAgentRef,
|
||||
OperationSampleMetadata, OperationSummary, OperationUsageSummary, OperationVersionRecord, Page,
|
||||
PlatformApiKeyRecord, PublishAgentRequest, PublishRequest, PublishedAgentTool,
|
||||
RegistryOperation, RotateSecretRequest, SampleKind, SaveAgentBindingsRequest,
|
||||
SaveAuthProfileRequest, SaveDescriptorMetadataRequest, SaveSampleMetadataRequest,
|
||||
SaveWorkspaceUpstreamRequest, SecretRecord, SecretVersionRecord, SessionRecord,
|
||||
UpdateWorkspaceRequest, UsageAgentBreakdown, UsageBucket, UsageOperationBreakdown, UsageQuery,
|
||||
UsageRollupRecord, UsageSummary, UsageTimelinePoint, WorkspaceMembershipRecord,
|
||||
WorkspaceRecord, WorkspaceUpstream, WorkspaceUpstreamId, YamlImportJob,
|
||||
YamlImportJobCompletion, YamlImportJobId, YamlImportJobStatus,
|
||||
};
|
||||
pub use postgres::{PostgresPoolConfig, PostgresPoolConfigError, PostgresRegistry};
|
||||
|
||||
@@ -524,6 +524,13 @@ pub struct CreateApprovalRequest<'a> {
|
||||
pub approval: &'a ApprovalRequest,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ListApprovalRequestsQuery<'a> {
|
||||
pub workspace_id: &'a WorkspaceId,
|
||||
pub status: Option<ApprovalRequestStatus>,
|
||||
pub limit: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DecideApprovalRequest<'a> {
|
||||
pub workspace_id: &'a WorkspaceId,
|
||||
|
||||
@@ -140,6 +140,83 @@ impl PostgresRegistry {
|
||||
row.map(map_approval_request_row).transpose()
|
||||
}
|
||||
|
||||
pub async fn list_approval_requests(
|
||||
&self,
|
||||
query: ListApprovalRequestsQuery<'_>,
|
||||
) -> Result<Vec<ApprovalRequestRecord>, RegistryError> {
|
||||
let status = query
|
||||
.status
|
||||
.map(|status| serialize_enum_text(&status, "approval_status"))
|
||||
.transpose()?;
|
||||
let rows = sqlx::query(
|
||||
"select
|
||||
id,
|
||||
workspace_id,
|
||||
agent_id,
|
||||
operation_id,
|
||||
operation_version,
|
||||
status,
|
||||
risk_level,
|
||||
confirmation_title,
|
||||
confirmation_body,
|
||||
request_payload_json,
|
||||
response_payload_json,
|
||||
created_at,
|
||||
expires_at,
|
||||
decided_at,
|
||||
decided_by_key_id,
|
||||
decision_note
|
||||
from approval_requests
|
||||
where workspace_id = $1
|
||||
and ($2::text is null or status = $2)
|
||||
order by created_at desc
|
||||
limit $3",
|
||||
)
|
||||
.bind(query.workspace_id.as_str())
|
||||
.bind(status.as_deref())
|
||||
.bind(i64::from(query.limit))
|
||||
.fetch_all(&self.pool)
|
||||
.await?;
|
||||
|
||||
rows.into_iter().map(map_approval_request_row).collect()
|
||||
}
|
||||
|
||||
pub async fn get_approval_request(
|
||||
&self,
|
||||
workspace_id: &WorkspaceId,
|
||||
approval_id: &ApprovalRequestId,
|
||||
) -> Result<Option<ApprovalRequestRecord>, RegistryError> {
|
||||
let row = sqlx::query(
|
||||
"select
|
||||
id,
|
||||
workspace_id,
|
||||
agent_id,
|
||||
operation_id,
|
||||
operation_version,
|
||||
status,
|
||||
risk_level,
|
||||
confirmation_title,
|
||||
confirmation_body,
|
||||
request_payload_json,
|
||||
response_payload_json,
|
||||
created_at,
|
||||
expires_at,
|
||||
decided_at,
|
||||
decided_by_key_id,
|
||||
decision_note
|
||||
from approval_requests
|
||||
where workspace_id = $1
|
||||
and id = $2
|
||||
limit 1",
|
||||
)
|
||||
.bind(workspace_id.as_str())
|
||||
.bind(approval_id.as_str())
|
||||
.fetch_optional(&self.pool)
|
||||
.await?;
|
||||
|
||||
row.map(map_approval_request_row).transpose()
|
||||
}
|
||||
|
||||
pub async fn decide_approval_request(
|
||||
&self,
|
||||
request: DecideApprovalRequest<'_>,
|
||||
|
||||
@@ -36,16 +36,16 @@ use crate::{
|
||||
CreatePlatformApiKeyRequest, CreateSecretRequest, CreateVersionRequest,
|
||||
CreateWorkspaceRequest, CreateYamlImportJobRequest, DecideApprovalRequest,
|
||||
DescriptorMetadata, ExpireApprovalRequest, FinishApprovalRequest, FinishImportJobRequest,
|
||||
ImportJob, ImportJobId, InvitationRecord, InvocationLogRecord, ListInvocationLogsQuery,
|
||||
MembershipRecord, OperationAgentRef, OperationSampleMetadata, OperationSummary,
|
||||
OperationUsageSummary, OperationVersionRecord, PlatformApiKeyRecord, PublishAgentRequest,
|
||||
PublishRequest, PublishedAgentTool, RegistryOperation, RotateSecretRequest,
|
||||
SaveAgentBindingsRequest, SaveAuthProfileRequest, SaveDescriptorMetadataRequest,
|
||||
SaveSampleMetadataRequest, SaveWorkspaceUpstreamRequest, SecretRecord, SecretVersionRecord,
|
||||
SessionRecord, UpdateWorkspaceRequest, UsageAgentBreakdown, UsageOperationBreakdown,
|
||||
UsageQuery, UsageRollupRecord, UsageSummary, UsageTimelinePoint, WorkspaceMembershipRecord,
|
||||
WorkspaceRecord, WorkspaceUpstream, YamlImportJob, YamlImportJobCompletion,
|
||||
YamlImportJobId, YamlImportJobStatus,
|
||||
ImportJob, ImportJobId, InvitationRecord, InvocationLogRecord, ListApprovalRequestsQuery,
|
||||
ListInvocationLogsQuery, MembershipRecord, OperationAgentRef, OperationSampleMetadata,
|
||||
OperationSummary, OperationUsageSummary, OperationVersionRecord, PlatformApiKeyRecord,
|
||||
PublishAgentRequest, PublishRequest, PublishedAgentTool, RegistryOperation,
|
||||
RotateSecretRequest, SaveAgentBindingsRequest, SaveAuthProfileRequest,
|
||||
SaveDescriptorMetadataRequest, SaveSampleMetadataRequest, SaveWorkspaceUpstreamRequest,
|
||||
SecretRecord, SecretVersionRecord, SessionRecord, UpdateWorkspaceRequest,
|
||||
UsageAgentBreakdown, UsageOperationBreakdown, UsageQuery, UsageRollupRecord, UsageSummary,
|
||||
UsageTimelinePoint, WorkspaceMembershipRecord, WorkspaceRecord, WorkspaceUpstream,
|
||||
YamlImportJob, YamlImportJobCompletion, YamlImportJobId, YamlImportJobStatus,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ use crank_registry::{
|
||||
CreateAgentRequest, CreateApprovalRequest, CreateInvocationLogRequest,
|
||||
CreatePlatformApiKeyRequest, CreateVersionRequest, CreateWorkspaceRequest,
|
||||
CreateYamlImportJobRequest, DecideApprovalRequest, DescriptorKind, DescriptorMetadata,
|
||||
FinishApprovalRequest, OperationSampleMetadata, PlatformApiKeyRecord, PostgresRegistry,
|
||||
PublishAgentRequest, PublishRequest, RegistryError, RegistryOperation, SampleKind,
|
||||
SaveAuthProfileRequest, SaveDescriptorMetadataRequest, SaveSampleMetadataRequest,
|
||||
UpdateWorkspaceRequest, WorkspaceRecord, YamlImportJobCompletion, YamlImportJobId,
|
||||
YamlImportJobStatus,
|
||||
FinishApprovalRequest, ListApprovalRequestsQuery, OperationSampleMetadata,
|
||||
PlatformApiKeyRecord, PostgresRegistry, PublishAgentRequest, PublishRequest, RegistryError,
|
||||
RegistryOperation, SampleKind, SaveAuthProfileRequest, SaveDescriptorMetadataRequest,
|
||||
SaveSampleMetadataRequest, UpdateWorkspaceRequest, WorkspaceRecord, YamlImportJobCompletion,
|
||||
YamlImportJobId, YamlImportJobStatus,
|
||||
};
|
||||
|
||||
fn test_workspace_id() -> WorkspaceId {
|
||||
@@ -531,6 +531,24 @@ async fn manages_approval_request_lifecycle() {
|
||||
assert_eq!(pending.len(), 1);
|
||||
assert_eq!(pending[0].approval, approval);
|
||||
|
||||
let workspace_approvals = registry
|
||||
.list_approval_requests(ListApprovalRequestsQuery {
|
||||
workspace_id: &workspace_id,
|
||||
status: None,
|
||||
limit: 10,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(workspace_approvals.len(), 1);
|
||||
assert_eq!(workspace_approvals[0].approval.id, approval.id);
|
||||
|
||||
let fetched = registry
|
||||
.get_approval_request(&workspace_id, &approval.id)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert_eq!(fetched.approval, approval);
|
||||
|
||||
let decided = registry
|
||||
.decide_approval_request(DecideApprovalRequest {
|
||||
workspace_id: &workspace_id,
|
||||
@@ -575,6 +593,20 @@ async fn manages_approval_request_lifecycle() {
|
||||
Some(json!({"id": "lead_123"}))
|
||||
);
|
||||
|
||||
let completed_by_status = registry
|
||||
.list_approval_requests(ListApprovalRequestsQuery {
|
||||
workspace_id: &workspace_id,
|
||||
status: Some(ApprovalRequestStatus::Completed),
|
||||
limit: 10,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(completed_by_status.len(), 1);
|
||||
assert_eq!(
|
||||
completed_by_status[0].approval.status,
|
||||
ApprovalRequestStatus::Completed
|
||||
);
|
||||
|
||||
let pending_after_decision = registry
|
||||
.list_pending_approval_requests_for_agent(&workspace_id, &agent.id)
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user