Commit Graph

7 Commits

Author SHA1 Message Date
Chris Farhood 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>
2026-02-11 21:41:09 -05:00
Chris Farhood 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>
2026-02-11 21:30:48 -05:00
Chris Farhood 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>
2026-02-11 21:24:17 -05:00
Chris Farhood 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>
2026-02-11 21:17:45 -05:00
Chris Farhood 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>
2026-02-11 21:09:10 -05:00
Chris Farhood b0d86831b7 Add publishing documentation and guides 2026-02-11 20:32:26 -05:00
Chris Farhood 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
2026-02-11 20:31:20 -05:00