feat: bump to v0.1.23 with security metrics and UI improvements

- Bump agent and server versions to 0.1.23
- Implement security metrics collection (bound agents, command processing, version compliance)
- Add dismiss button for timed out commands in agent status
- Add config sync endpoint for server->agent configuration updates
- Add ignored updates workflow in AgentUpdatesEnhanced (approve/reject workflow)
- Swap AgentScanners layout (subsystems top, security bottom)
- Replace placeholder security data with database metrics
- Add backpressure detection based on pending command ratios
This commit is contained in:
Fimeg
2025-11-04 09:41:27 -05:00
parent 38894f64d3
commit 95f70bd9bb
12 changed files with 511 additions and 244 deletions

View File

@@ -40,7 +40,7 @@ interface LogResponse {
result: string;
}
type StatusTab = 'pending' | 'approved' | 'installing' | 'installed';
type StatusTab = 'pending' | 'approved' | 'installing' | 'installed' | 'ignored';
export function AgentUpdatesEnhanced({ agentId }: AgentUpdatesEnhancedProps) {
const [activeStatus, setActiveStatus] = useState<StatusTab>('pending');
@@ -123,6 +123,21 @@ export function AgentUpdatesEnhanced({ agentId }: AgentUpdatesEnhancedProps) {
},
});
const rejectMutation = useMutation({
mutationFn: async (updateId: string) => {
const response = await updateApi.rejectUpdate(updateId);
return response;
},
onSuccess: () => {
toast.success('Update rejected');
refetch();
queryClient.invalidateQueries({ queryKey: ['agent-updates'] });
},
onError: (error: any) => {
toast.error(`Failed to reject: ${error.message || 'Unknown error'}`);
},
});
const getLogsMutation = useMutation({
mutationFn: async (commandId: string) => {
setIsLoadingLogs(true);
@@ -182,6 +197,10 @@ export function AgentUpdatesEnhanced({ agentId }: AgentUpdatesEnhancedProps) {
installMutation.mutate(updateId);
};
const handleReject = async (updateId: string) => {
rejectMutation.mutate(updateId);
};
const handleBulkApprove = async () => {
if (selectedUpdates.length === 0) {
toast.error('Select at least one update');
@@ -241,6 +260,7 @@ export function AgentUpdatesEnhanced({ agentId }: AgentUpdatesEnhancedProps) {
{ key: 'approved', label: 'Approved' },
{ key: 'installing', label: 'Installing' },
{ key: 'installed', label: 'Installed' },
{ key: 'ignored', label: 'Ignored' },
].map((tab) => (
<button
key={tab.key}
@@ -387,12 +407,20 @@ export function AgentUpdatesEnhanced({ agentId }: AgentUpdatesEnhancedProps) {
<div className="flex items-center space-x-2 flex-shrink-0">
{activeStatus === 'pending' && (
<button
onClick={(e) => { e.stopPropagation(); handleApprove(update.id); }}
className="text-xs text-gray-600 hover:text-gray-900 px-2 py-1"
>
Approve
</button>
<>
<button
onClick={(e) => { e.stopPropagation(); handleApprove(update.id); }}
className="text-xs text-gray-600 hover:text-gray-900 px-2 py-1"
>
Approve
</button>
<button
onClick={(e) => { e.stopPropagation(); handleReject(update.id); }}
className="text-xs text-red-600 hover:text-red-800 px-2 py-1"
>
Reject
</button>
</>
)}
{activeStatus === 'approved' && (
<button
@@ -402,6 +430,11 @@ export function AgentUpdatesEnhanced({ agentId }: AgentUpdatesEnhancedProps) {
Install
</button>
)}
{activeStatus === 'ignored' && (
<span className="text-xs text-gray-500 px-2 py-1">
Rejected
</span>
)}
{update.recent_command_id && (
<button
onClick={(e) => { e.stopPropagation(); handleViewLogs(update); }}