feat(V2.2): bulk revocation — filter-based fleet-wide certificate revocation

Add POST /api/v1/certificates/bulk-revoke with filter criteria (profile_id,
owner_id, agent_id, issuer_id, team_id, certificate_ids), partial-failure
tolerance, and audit trail. Includes MCP tool, CLI command (certs bulk-revoke),
server-side bulk modal in GUI replacing client-side sequential loop, OpenAPI
spec, compliance mapping updates, and 21 new tests (12 service, 7 handler,
1 CLI, 1 frontend).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Shankar
2026-04-16 00:06:34 -04:00
parent cdb448dfe5
commit 4e3927e8b4
25 changed files with 1264 additions and 39 deletions
+10
View File
@@ -11,6 +11,7 @@ import {
updateCertificate,
archiveCertificate,
revokeCertificate,
bulkRevokeCertificates,
exportCertificatePEM,
downloadCertificatePEM,
exportCertificatePKCS12,
@@ -288,6 +289,15 @@ describe('API Client', () => {
expect(init.method).toBe('POST');
expect(JSON.parse(init.body)).toEqual({ reason: 'keyCompromise' });
});
it('bulkRevokeCertificates sends POST with criteria', async () => {
mockFetch.mockReturnValueOnce(mockJsonResponse({ total_matched: 3, total_revoked: 2, total_skipped: 1, total_failed: 0 }));
await bulkRevokeCertificates({ reason: 'keyCompromise', profile_id: 'prof-tls', certificate_ids: ['mc-1', 'mc-2'] });
const [url, init] = mockFetch.mock.calls[0];
expect(url).toBe('/api/v1/certificates/bulk-revoke');
expect(init.method).toBe('POST');
expect(JSON.parse(init.body)).toEqual({ reason: 'keyCompromise', profile_id: 'prof-tls', certificate_ids: ['mc-1', 'mc-2'] });
});
});
// ─── Agents ─────────────────────────────────────────