Files
stack/apps/api/src/federation/audit.service.ts
T
Jason WoltjeandClaude Sonnet 4.5 0495f979a7 feat(#94): implement spoke configuration UI
Implements the final piece of M7-Federation - the spoke configuration UI
that allows administrators to configure their local instance's federation
capabilities and settings.

Backend Changes:
- Add UpdateInstanceDto with validation for name, capabilities, and metadata
- Implement FederationService.updateInstanceConfiguration() method
- Add PATCH /api/v1/federation/instance endpoint to FederationController
- Add audit logging for configuration updates
- Add tests for updateInstanceConfiguration (5 new tests, all passing)

Frontend Changes:
- Create SpokeConfigurationForm component with PDA-friendly design
- Create /federation/settings page with configuration management
- Add regenerate keypair functionality with confirmation dialog
- Extend federation API client with updateInstanceConfiguration and regenerateInstanceKeys
- Add comprehensive tests (10 tests, all passing)

Design Decisions:
- Admin-only access via AdminGuard
- Never expose private key in API responses (security)
- PDA-friendly language throughout (no demanding terms)
- Clear visual hierarchy with read-only and editable fields
- Truncated public key with copy button for usability
- Confirmation dialog for destructive key regeneration

All tests passing:
- Backend: 13/13 federation service tests passing
- Frontend: 10/10 SpokeConfigurationForm tests passing
- TypeScript compilation: passing
- Linting: passing
- PDA-friendliness: verified

This completes M7-Federation. All federation features are now implemented.

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
2026-02-03 14:51:59 -06:00

127 lines
3.1 KiB
TypeScript

/**
* Federation Audit Service
*
* Logs security-sensitive operations for compliance and monitoring.
* Uses application logger since ActivityLog requires workspace context.
*/
import { Injectable, Logger } from "@nestjs/common";
@Injectable()
export class FederationAuditService {
private readonly logger = new Logger(FederationAuditService.name);
/**
* Log instance keypair regeneration (system-level operation)
* Logged to application logs for security audit trail
*/
logKeypairRegeneration(userId: string, instanceId: string): void {
this.logger.warn({
event: "FEDERATION_KEYPAIR_REGENERATED",
userId,
instanceId,
timestamp: new Date().toISOString(),
securityEvent: true,
});
}
/**
* Log instance configuration update (system-level operation)
* Logged to application logs for security audit trail
*/
logInstanceConfigurationUpdate(
userId: string,
instanceId: string,
updates: Record<string, unknown>
): void {
this.logger.log({
event: "FEDERATION_INSTANCE_CONFIG_UPDATED",
userId,
instanceId,
updates,
timestamp: new Date().toISOString(),
securityEvent: true,
});
}
/**
* Log federated authentication initiation
*/
logFederatedAuthInitiation(userId: string, remoteInstanceId: string): void {
this.logger.log({
event: "FEDERATION_AUTH_INITIATED",
userId,
remoteInstanceId,
timestamp: new Date().toISOString(),
});
}
/**
* Log federated identity linking
*/
logFederatedIdentityLinked(userId: string, remoteInstanceId: string): void {
this.logger.log({
event: "FEDERATION_IDENTITY_LINKED",
userId,
remoteInstanceId,
timestamp: new Date().toISOString(),
securityEvent: true,
});
}
/**
* Log federated identity revocation
*/
logFederatedIdentityRevoked(userId: string, remoteInstanceId: string): void {
this.logger.warn({
event: "FEDERATION_IDENTITY_REVOKED",
userId,
remoteInstanceId,
timestamp: new Date().toISOString(),
securityEvent: true,
});
}
/**
* Log identity verification attempt
*/
logIdentityVerification(userId: string, remoteInstanceId: string, success: boolean): void {
const level = success ? "log" : "warn";
this.logger[level]({
event: "FEDERATION_IDENTITY_VERIFIED",
userId,
remoteInstanceId,
success,
timestamp: new Date().toISOString(),
securityEvent: true,
});
}
/**
* Log identity linking (create mapping)
*/
logIdentityLinking(localUserId: string, remoteInstanceId: string, remoteUserId: string): void {
this.logger.log({
event: "FEDERATION_IDENTITY_LINKED",
localUserId,
remoteUserId,
remoteInstanceId,
timestamp: new Date().toISOString(),
securityEvent: true,
});
}
/**
* Log identity revocation (remove mapping)
*/
logIdentityRevocation(localUserId: string, remoteInstanceId: string): void {
this.logger.warn({
event: "FEDERATION_IDENTITY_REVOKED",
localUserId,
remoteInstanceId,
timestamp: new Date().toISOString(),
securityEvent: true,
});
}
}