feat: production readiness improvements

## Error Handling
- Add GlobalErrorBoundary with error classification and recovery
- Add custom error types (SecurityError, ConnectionError, TimeoutError)
- Fix ErrorAlert component syntax errors

## Offline Mode
- Add offlineStore for offline state management
- Implement message queue with localStorage persistence
- Add exponential backoff reconnection (1s→60s)
- Add OfflineIndicator component with status display
- Queue messages when offline, auto-retry on reconnect

## Security Hardening
- Add AES-256-GCM encryption for chat history storage
- Add secure API key storage with OS keychain integration
- Add security audit logging system
- Add XSS prevention and input validation utilities
- Add rate limiting and token generation helpers

## CI/CD (Gitea Actions)
- Add .gitea/workflows/ci.yml for continuous integration
- Add .gitea/workflows/release.yml for release automation
- Support Windows Tauri build and release

## UI Components
- Add LoadingSpinner, LoadingOverlay, LoadingDots components
- Add MessageSkeleton, ConversationListSkeleton skeletons
- Add EmptyMessages, EmptyConversations empty states
- Integrate loading states in ChatArea and ConversationList

## E2E Tests
- Fix WebSocket mock for streaming response tests
- Fix approval endpoint route matching
- Add store state exposure for testing
- All 19 core-features tests now passing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-22 00:03:22 +08:00
parent ce562e8bfc
commit 185763868a
27 changed files with 5725 additions and 268 deletions

View File

@@ -0,0 +1,241 @@
/**
* Security Module Index
*
* Central export point for all security-related functionality in ZCLAW.
*
* Modules:
* - crypto-utils: AES-256-GCM encryption, key derivation, hashing
* - secure-storage: OS keychain integration with encrypted localStorage fallback
* - api-key-storage: Secure API key management
* - encrypted-chat-storage: Encrypted chat history persistence
* - security-audit: Security event logging and reporting
* - security-utils: Input validation, XSS prevention, rate limiting
*/
// Re-export crypto utilities
export {
// Core encryption
encrypt,
decrypt,
encryptObject,
decryptObject,
deriveKey,
generateMasterKey,
generateSalt,
// Hashing
hashSha256,
hashSha512,
// Utilities
arrayToBase64,
base64ToArray,
constantTimeEqual,
generateRandomString,
secureWipe,
clearKeyCache,
isCryptoAvailable,
isValidEncryptedData,
} from './crypto-utils';
export type { EncryptedData } from './crypto-utils';
// Re-export secure storage
export {
secureStorage,
secureStorageSync,
isSecureStorageAvailable,
storeDeviceKeys,
getDeviceKeys,
deleteDeviceKeys,
hasDeviceKeys,
getDeviceKeysCreatedAt,
} from './secure-storage';
export type { Ed25519KeyPair } from './secure-storage';
// Re-export API key storage
export {
// Types
type ApiKeyType,
type ApiKeyMetadata,
// Core functions
storeApiKey,
getApiKey,
deleteApiKey,
listApiKeyMetadata,
updateApiKeyMetadata,
hasApiKey,
validateStoredApiKey,
rotateApiKey,
// Utility functions
validateApiKeyFormat,
exportApiKeyConfig,
isUsingKeychain,
generateTestApiKey,
} from './api-key-storage';
// Re-export encrypted chat storage
export {
initializeEncryptedChatStorage,
saveConversations,
loadConversations,
clearAllChatData,
exportEncryptedBackup,
importEncryptedBackup,
isEncryptedStorageActive,
getStorageStats,
rotateEncryptionKey,
} from './encrypted-chat-storage';
// Re-export security audit
export {
// Core logging
logSecurityEvent,
logAuthEvent,
logKeyEvent,
logDataEvent,
logSecurityViolation,
logDecryptionFailure,
logIntegrityFailure,
logPermissionEvent,
logSessionEvent,
logSuspiciousActivity,
logRateLimitEvent,
// Query functions
getSecurityEvents,
getSecurityEventsByType,
getSecurityEventsBySeverity,
getSecurityEventsByTimeRange,
getRecentCriticalEvents,
getSecurityEventsBySession,
// Report generation
generateSecurityAuditReport,
// Maintenance
clearSecurityAuditLog,
exportSecurityEvents,
importSecurityEvents,
verifyAuditLogIntegrity,
// Session management
getCurrentSessionId,
setCurrentSessionId,
setAuditEnabled,
isAuditEnabledState,
initializeSecurityAudit,
shutdownSecurityAudit,
} from './security-audit';
export type {
SecurityEventType,
SecurityEventSeverity,
SecurityEvent,
SecurityAuditReport,
} from './security-audit';
// Re-export security utilities
export {
// HTML sanitization
escapeHtml,
unescapeHtml,
sanitizeHtml,
// URL validation
validateUrl,
isSafeRedirectUrl,
// Path validation
validatePath,
// Input validation
isValidEmail,
isValidUsername,
validatePasswordStrength,
sanitizeFilename,
sanitizeJson,
// Rate limiting
isRateLimited,
resetRateLimit,
getRemainingAttempts,
// CSP helpers
generateCspNonce,
buildCspHeader,
DEFAULT_CSP_DIRECTIVES,
// Security checks
checkSecurityHeaders,
// Random generation
generateSecureToken,
generateSecureId,
} from './security-utils';
// ============================================================================
// Security Initialization
// ============================================================================
/**
* Initialize all security modules
* Call this during application startup
*/
export async function initializeSecurity(sessionId?: string): Promise<void> {
// Initialize security audit first
const { initializeSecurityAudit } = await import('./security-audit');
initializeSecurityAudit(sessionId);
// Initialize encrypted chat storage
const { initializeEncryptedChatStorage } = await import('./encrypted-chat-storage');
await initializeEncryptedChatStorage();
console.log('[Security] All security modules initialized');
}
/**
* Shutdown all security modules
* Call this during application shutdown
*/
export async function shutdownSecurity(): Promise<void> {
const { shutdownSecurityAudit } = await import('./security-audit');
shutdownSecurityAudit();
const { clearKeyCache } = await import('./crypto-utils');
clearKeyCache();
console.log('[Security] All security modules shut down');
}
/**
* Get a comprehensive security status report
*/
export async function getSecurityStatus(): Promise<{
auditEnabled: boolean;
keychainAvailable: boolean;
chatStorageInitialized: boolean;
storedApiKeys: number;
recentEvents: number;
criticalEvents: number;
}> {
const { isAuditEnabledState, getSecurityEventsBySeverity } = await import('./security-audit');
const { isSecureStorageAvailable } = await import('./secure-storage');
const { isEncryptedStorageActive: isChatStorageInitialized } = await import('./encrypted-chat-storage');
const { listApiKeyMetadata } = await import('./api-key-storage');
const criticalEvents = getSecurityEventsBySeverity('critical').length;
const errorEvents = getSecurityEventsBySeverity('error').length;
return {
auditEnabled: isAuditEnabledState(),
keychainAvailable: await isSecureStorageAvailable(),
chatStorageInitialized: await isChatStorageInitialized(),
storedApiKeys: (await listApiKeyMetadata()).length,
recentEvents: criticalEvents + errorEvents,
criticalEvents,
};
}