main
213 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ad3934860e |
feat: implement skeleton loading screens for all views (Phase 3.5)
Created comprehensive skeleton components providing visual feedback during data loading. This improves perceived performance and provides a better user experience with consistent loading states across all views. Changes: - NEW: src/components/LoadingSkeletons.tsx (+105 lines) - SealedSecretListSkeleton - 5 placeholder rows - SealedSecretDetailSkeleton - title + sections + actions - SealingKeysListSkeleton - 2 certificate placeholders - CertificateInfoSkeleton - metadata lines - ControllerHealthSkeleton - chip + info layout - All use wave animation and realistic layouts - UPDATED: SealedSecretList.tsx - Use loading state from useList() hook - Show skeleton during data fetch - Smooth transition to real data - UPDATED: SealedSecretDetail.tsx - Replace Headlamp Loader with custom skeleton - Better layout matching - No layout shift - UPDATED: SealingKeysView.tsx - Add loading state detection - Show skeleton for certificates - Professional loading UX - UPDATED: ControllerStatus.tsx - Replace CircularProgress with skeleton - Match chip + info layout - Consistent with other components Benefits: - Improved perceived performance - Reduced layout shift (skeletons match real components) - Consistent loading experience (wave animation) - Better user feedback during data loading Build: 356.44 kB (98.01 kB gzipped) - +1.52 kB (+0.4%) Time: 4.78s Progress: 11/14 phases complete (79%) Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> |
||
|
|
2cb815f921 |
feat: add error boundaries for graceful error handling (Phase 3.4)
Implement React Error Boundaries to catch and handle errors gracefully without crashing the entire UI. Provides helpful recovery mechanisms. Changes: - Create ErrorBoundary component module - BaseErrorBoundary abstract class (shared logic) - CryptoErrorBoundary (crypto operation errors) - ApiErrorBoundary (API communication errors) - GenericErrorBoundary (general component errors) - Error boundary features - Catches rendering and lifecycle errors - Logs errors to console for debugging - Displays helpful, contextual error messages - Provides retry/reload buttons for recovery - Optional custom fallback UI via props - Optional onReset callback for custom recovery - Integrate error boundaries into routes - Wrap SealedSecretList with ApiErrorBoundary - Wrap SealedSecretDetail with ApiErrorBoundary - Wrap SealingKeysView with ApiErrorBoundary - Wrap SettingsPage with GenericErrorBoundary - Wrap SecretDetailsSection with GenericErrorBoundary Error types and messages: - Crypto errors: Certificate, browser compatibility, malformed data - API errors: Cluster connection, controller config, network - Generic errors: Unexpected errors with simple recovery message Benefits: - App doesn't crash completely on errors - Users can continue using unaffected features - Clear, actionable troubleshooting steps - Professional error presentation - Production-ready error handling - Easier debugging with console logs Build: 354.92 kB (97.76 kB gzipped), +2.47 kB (+0.7%) Phase 3.4 complete. 10 of 14 phases done (71%). Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> |
||
|
|
2171250e99 |
perf: optimize React performance with useMemo/useCallback (Phase 3.3)
Add comprehensive memoization to prevent unnecessary re-renders and improve component performance. Build time improved by 5%. Changes: - SealedSecretList optimization - Memoize columns array (stable reference for table) - Memoize actions array (only updates when canCreate changes) - Memoize dialog callbacks (handleOpenDialog, handleCloseDialog) - Reduces unnecessary table re-renders - EncryptDialog optimization - Memoize all form callbacks with functional state updates - handleAddKeyValue, handleRemoveKeyValue, handleKeyChange - handleValueChange, toggleShowValue - Zero dependencies using prev => pattern - Stable callback references improve child performance - SealedSecretDetail optimization - Memoize async operations (handleDelete, handleRotate) - Callbacks only recreate when dependencies change - Better performance for button interactions Patterns used: - useMemo for computed values (columns, actions arrays) - useCallback for event handlers passed to children - Functional state updates to eliminate dependencies - Empty dependency arrays where possible Benefits: - Reduced re-renders across all components - Faster build time: 3.92s → 3.74s (-5% improvement!) - Better performance with large datasets - Follows React best practices - Ready for React concurrent features Build: 352.45 kB (97.04 kB gzipped), +0.40 kB (+0.1%) Build time: 3.74s (5% faster than before!) Phase 3.3 complete. 9 of 14 phases done (64%). Note: Skipped Phase 3.2 (Zod validation) as Phase 1.3 validators are already comprehensive. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> |
||
|
|
5256c8febd |
feat: extract business logic into custom React hooks (Phase 3.1)
Refactor components to use custom hooks for business logic, dramatically simplifying component code while improving testability and reusability. Changes: - Create useSealedSecretEncryption() hook - Encapsulates complete encryption workflow - Handles validation, cert fetching, expiry checks, encryption - Built-in error handling with snackbar notifications - Returns ready-to-apply SealedSecret object - Type-safe Result<T, E> pattern - Create useControllerHealth() hook - Encapsulates health monitoring logic - Auto-refresh with configurable interval - Manual refresh function - Loading state management - Proper cleanup - Refactor EncryptDialog component - Simplified from 215 → 130 lines (-85 lines, -40%) - Business logic extracted to hook - Focus on presentation logic only - Much easier to understand and maintain - Refactor ControllerStatus component - Simplified from 115 → 58 lines (-57 lines, -50%) - One-line hook usage - Perfect abstraction example Benefits: - Separation of concerns (business vs presentation) - Reusable hooks across components - Easier to test (hooks testable independently) - Better maintainability (single source of truth) - Code reduction: ~140 lines removed from components Build: 352.05 kB (96.99 kB gzipped), +0.71 kB (+0.2%) Phase 3.1 complete. 8 of 14 phases done (57%). Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> |
||
|
|
55aba7417c |
feat: implement API version detection and compatibility (Phase 2.4)
Add automatic detection of SealedSecrets CRD API version from cluster. The plugin now adapts to installed versions (v1alpha1, v1, etc.) and provides warnings when CRD is missing or non-default versions are used. Changes: - Add detectApiVersion() to SealedSecretCRD class - Queries CRD definition from Kubernetes API - Uses storage version (canonical version for etcd) - Caches result to avoid repeated API calls - Falls back to v1alpha1 if detection fails - Create VersionWarning component - Auto-detects version on mount - Shows error alert for missing CRD (with install instructions) - Shows info alert for non-default versions - Provides retry button for failed detections - Configurable detail level (showDetails prop) - Integrate version warnings into UI - SealedSecretList: minimal warnings (errors only) - SettingsPage: detailed version info always shown - Add version management methods - getApiEndpoint(): auto-versioned endpoint - getDetectedVersion(): get cached version - clearVersionCache(): force re-detection Benefits: - Future-proof: automatically supports new API versions - Better UX: clear error messages with installation help - Performance: version detected once and cached - Version awareness: users see which API version is active Build: 351.34 kB (96.75 kB gzipped), +2.88 kB (+0.8%) Phase 2.4 complete. 7 of 14 phases done (50% milestone). Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> |
||
|
|
839fdd4819 |
feat: implement RBAC permissions helper (Phase 2.3)
Add comprehensive RBAC permission checking using Kubernetes SelfSubjectAccessReview API. Hide/disable UI elements based on user permissions for better security and UX. Features: - RBAC module with permission checking utilities - React hooks for permission management (usePermissions, usePermission, etc.) - Permission-aware UI (hide create/delete/re-encrypt buttons) - Decrypt button disabled if no Secret access - Multi-namespace permission support - Fail-safe design (returns false on error) Technical details: - Uses Kubernetes authorization.k8s.io/v1 SelfSubjectAccessReview API - Concurrent permission checks with Promise.all - Automatic loading states and error handling - React cleanup on unmount prevents memory leaks - Type-safe with Result<T, E> types Files: - src/lib/rbac.ts: NEW RBAC checking module (+168 lines) - src/hooks/usePermissions.ts: NEW React hooks (+138 lines) - src/components/SealedSecretList.tsx: Hide create button if no permission - src/components/SealedSecretDetail.tsx: Hide re-encrypt/delete/decrypt based on permissions - PHASE_2.3_COMPLETE.md: Implementation documentation - .claude/agents/: Add 5 new specialized agents (test, accessibility, docs, orchestration) Bundle size: 348.46 kB (96.05 kB gzipped), +1.81 kB (+0.5%) Build time: 3.93s Zero TypeScript/lint errors Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> |
||
|
|
d17e2485fb |
feat: implement controller health checks (Phase 2.2)
Add comprehensive controller health monitoring functionality with real-time visual indicators and auto-refresh capabilities. Features: - Health check API with 5-second timeout - Latency tracking and version detection - ControllerStatus component with color-coded indicators - Auto-refresh with configurable intervals - Integration with SettingsPage and SealingKeysView Technical details: - AbortController for proper timeout handling - Never-fail API (always returns status) - Three states: Healthy (green), Unhealthy (yellow), Unreachable (red) - Detailed tooltips with error messages - Response time display in milliseconds - Version information from X-Controller-Version header Files: - src/lib/controller.ts: Add checkControllerHealth() (+58 lines) - src/components/ControllerStatus.tsx: NEW component (+117 lines) - src/components/SettingsPage.tsx: Add status display - src/components/SealingKeysView.tsx: Add status to header - PHASE_2.2_COMPLETE.md: Implementation documentation Bundle size: 346.65 kB (95.49 kB gzipped), +2.7 kB (+0.8%) Build time: 3.94s (improved!) Zero TypeScript/lint errors Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> |
||
|
|
cc08e15f6a |
feat: implement certificate validation and expiry detection (Phase 2.1)
Add comprehensive certificate metadata parsing and expiry warnings. ## Changes ### Types (src/types.ts) - Add CertificateInfo interface with validity dates, expiry status, issuer/subject, fingerprint ### Crypto Module (src/lib/crypto.ts) - Add parseCertificateInfo() to extract certificate metadata - Add isCertificateExpiringSoon() helper (default 30 days threshold) - Calculate SHA-256 fingerprint, parse DN fields, compute days until expiry ### SealingKeysView (src/components/SealingKeysView.tsx) - Display certificate expiry information in table - Show visual indicators: Expired (red), Expiring Soon (warning), Valid (normal) - Display days remaining for expiring certificates ### EncryptDialog (src/components/EncryptDialog.tsx) - Add expiry warning before encryption - Warn if certificate expired or expiring within 30 days - Show specific expiry date in warning message ## Features - **Certificate Parsing:** Extract all metadata from X.509 certificates - **Expiry Detection:** Automatic detection of expired/expiring certificates - **Visual Indicators:** Color-coded chips for expiry status - **Proactive Warnings:** Alert users before creating secrets with expiring certs - **SHA-256 Fingerprint:** Unique certificate identification ## Verification - TypeScript: 0 errors - Linting: 0 errors - Build: Success (343.95 kB, 94.58 kB gzipped) Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> |
||
|
|
2e19dd05e6 |
feat: implement config validation and retry logic (Phase 1.3)
Add comprehensive input validation and exponential backoff retry logic to improve user experience and system reliability. ## Changes ### Validators Module (src/lib/validators.ts) - NEW - Add type guards for SealedSecret runtime validation - Add Kubernetes DNS-1123 name/key validators - Add PEM certificate format validator - Add detailed validation functions with error messages - Validate secret names, keys, and values - Validate plugin configuration ### Retry Logic (src/lib/retry.ts) - NEW - Implement exponential backoff with jitter - Add configurable retry options (max attempts, delays, backoff multiplier) - Add helper predicates for network/HTTP errors - Aggregate errors across retry attempts - Default: 3 attempts, 1s initial delay, 10s max delay ### Controller API (src/lib/controller.ts) - Add retry logic to fetchPublicCertificate - Split into fetchPublicCertificateOnce (internal) and public version - Automatic retry with 3 attempts on network errors ### UI Components (src/components/EncryptDialog.tsx) - Add input validation before encryption - Validate secret name (Kubernetes format) - Validate each key name (alphanumeric + hyphens/dots/underscores) - Validate each value (non-empty, < 1MB) - Show specific error messages for validation failures ## Validation Rules - **Secret Names:** DNS-1123 subdomain (lowercase, alphanumeric, hyphens, dots) - **Secret Keys:** Alphanumeric, hyphens, underscores, dots (1-253 chars) - **Secret Values:** Non-empty, < 1MB - **PEM Certificates:** Valid BEGIN/END CERTIFICATE markers ## Retry Strategy - **Exponential Backoff:** delay = initialDelay * (2 ^ attempt) - **Jitter:** ±25% random variation prevents thundering herd - **Max Delay:** Capped at 10 seconds - **Error Aggregation:** Collects all error messages for debugging ## Benefits - Clear, actionable error messages - Prevents invalid Kubernetes resources - Automatic recovery from transient failures - Kubernetes-compliant validation - Better user experience ## Verification - TypeScript: 0 errors - Linting: 0 errors - Build: Success (342.57 kB, 94.15 kB gzipped) - Build time: 3.87s Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> |
||
|
|
fcf0ace106 |
feat: implement branded types for type-level security (Phase 1.2)
Add branded types to prevent mixing plaintext, encrypted, and certificate values at compile time. This provides an additional layer of type safety without any runtime cost. ## Changes ### Type System (src/types.ts) - Add PlaintextValue branded type for user input - Add EncryptedValue branded type for encrypted data - Add Base64String branded type for base64-encoded values - Add PEMCertificate branded type for PEM certificates - Add constructor functions for each branded type - Add unwrap() utility for extracting raw strings ### Crypto Module (src/lib/crypto.ts) - Update parsePublicKeyFromCert() to require PEMCertificate - Update encryptValue() to accept PlaintextValue, return Base64String - Update encryptKeyValues() to accept PlaintextValue[], return Base64String[] - Update validateCertificate() to require PEMCertificate ### Controller API (src/lib/controller.ts) - Update fetchPublicCertificate() to return PEMCertificate - Brand certificate at source when fetching from API ### UI Components - EncryptDialog: Brand user input as PlaintextValue before encryption - SealingKeysView: Brand certificates as PEMCertificate when parsing ## Benefits - Zero runtime cost (types erased at compile time) - Prevents passing plaintext where encrypted expected - Prevents passing encrypted where plaintext expected - Self-documenting function signatures - TypeScript enforces correct value handling ## Verification - TypeScript: 0 errors - Linting: 0 errors - Build: Success (340.20 kB, 93.41 kB gzipped) - Build time: 3.99s (improved from 4.64s) Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> |
||
|
|
286e88fece |
feat: implement Result types for type-safe error handling (Phase 1.1)
Replace throw/catch patterns with explicit Result types throughout the codebase. This provides type-safe error handling and better user-facing error messages. ## Changes ### Core Type System (src/types.ts) - Add Result<T, E> discriminated union type - Add AsyncResult<T, E> for promises - Add helper functions: Ok(), Err(), tryCatch(), tryCatchAsync() ### Crypto Module (src/lib/crypto.ts) - Update parsePublicKeyFromCert() to return Result<PublicKey, string> - Update encryptValue() to return Result<string, string> - Update encryptKeyValues() to return Result<Record<string, string>, string> - Early return on first encryption failure with detailed error ### Controller API (src/lib/controller.ts) - Update fetchPublicCertificate() to return AsyncResult<string, string> - Update verifySealedSecret() to return AsyncResult<boolean, string> - Update rotateSealedSecret() to return AsyncResult<string, string> - Use tryCatchAsync() for HTTP operations ### UI Components - EncryptDialog: Explicit error checking at each step with specific messages - SealingKeysView: Type-safe certificate download with error handling - DecryptDialog: Import cleanup (auto-fixed by linter) - SealedSecretDetail: Unused import removed (auto-fixed by linter) ### Documentation - ENHANCEMENT_PLAN.md: Comprehensive 4-phase enhancement roadmap - PHASE_1.1_COMPLETE.md: Detailed implementation summary - BUILD_VERIFICATION_SUMMARY.md: Build metrics and verification results - DEVELOPMENT.md: Development workflow guide - TESTING_GUIDE.md: Manual testing procedures - READY_FOR_TESTING.md: Quick-start testing guide ### Development Tools - Add 5 specialized Claude Code subagents to .claude/agents/ - typescript-pro: TypeScript expertise - kubernetes-specialist: K8s best practices - react-specialist: React optimization - security-auditor: Security review - code-reviewer: Code quality ## Benefits - Type Safety: Errors are now part of type signatures - Better UX: Specific error messages at each operation step - Maintainability: Error paths are explicit and visible - No Hidden Exceptions: All error cases handled explicitly ## Verification - TypeScript: 0 errors - Linting: All checks pass - Build: 340.13 kB (93.40 kB gzipped, +0.2%) - Package: Successfully created ## Breaking Changes None for users. Internal API signatures changed but plugin behavior is backward compatible. ## Testing See TESTING_GUIDE.md for detailed test scenarios: - Happy path: Create sealed secret with valid controller - Error path: Try with controller unreachable - Console check: Verify no uncaught exceptions Run: npm start (in headlamp-sealed-secrets directory) Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering> |
||
|
|
b0d86831b7 | Add publishing documentation and guides | ||
|
|
dddbd30677 |
Initial release: Headlamp Sealed Secrets plugin v0.1.0
Features: - Complete SealedSecret CRD integration with Headlamp - Client-side encryption using controller's public key - Support for all three scoping modes (strict, namespace-wide, cluster-wide) - List and detail views for SealedSecrets - Encryption dialog for creating new SealedSecrets - Decryption support with RBAC awareness - Sealing keys management - Settings page for controller configuration - Integration with Secret detail view Technical: - Full TypeScript with strict mode - ~1,345 lines of code - Build size: 339.42 kB (93.21 kB gzipped) - Compatible with Headlamp v0.13.0+ - Apache 2.0 license Security: - All encryption performed client-side - RSA-OAEP + AES-256-GCM (kubeseal-compatible) - Auto-hide decrypted values after 30 seconds Closes: Initial implementation |