# Keys & Secrets Management Page Implementation **Date:** 2026-02-05 **Status:** Complete ## Overview Implemented a comprehensive Keys & Secrets management page for the Attune web UI, enabling users to perform CRUD operations on encrypted secrets and configuration values with proper scoping and format validation. ## Changes Made ### New Files Created 1. **`attune/web/src/hooks/useKeys.ts`** - Custom React hooks for keys/secrets API operations - `useKeys()` - Fetch paginated list with filters - `useKey(ref)` - Fetch single key by reference (includes decrypted value) - `useCreateKey()` - Create new key mutation - `useUpdateKey()` - Update existing key mutation - `useDeleteKey()` - Delete key mutation - Proper query invalidation for cache management 2. **`attune/web/src/pages/keys/KeysPage.tsx`** - Main list view for keys and secrets - Search functionality (by reference or name) - Filter by scope (System, User, Pack, Action, Sensor) - Client-side search with server-side scope filtering - Pagination (20 items per page) - Color-coded scope badges - Encryption status indicators - Inline edit and delete actions - Empty states and error handling 3. **`attune/web/src/pages/keys/KeyCreateModal.tsx`** - Modal dialog for creating new keys - **Value format selection** with validation: - **Text** (can be encrypted) - **JSON** (can be encrypted, validates JSON syntax) - **YAML** (can be encrypted, basic validation) - **Number** (cannot be encrypted, validates numeric) - **Integer** (cannot be encrypted, validates integer) - **Boolean** (cannot be encrypted, validates true/false) - Encryption toggle (automatically disabled for non-encryptable formats) - Scope selection (System, User, Pack, Action, Sensor) - Owner identifier field (conditional based on scope) - Format-aware validation before submission - Reference format validation (alphanumeric, _, -, .) 4. **`attune/web/src/pages/keys/KeyEditModal.tsx`** - Modal dialog for editing existing keys - Shows key metadata (reference, scope, owner) as read-only - Editable name and value fields - Show/hide value toggle for security - Encryption toggle with warning when changing encryption status - Validates changes before submission - Visual warnings when changing encryption settings ### Modified Files 1. **`attune/web/src/App.tsx`** - Added route for `/keys` (KeysPage) - Imported KeysPage component 2. **`attune/web/src/components/layout/MainLayout.tsx`** - Added "Keys & Secrets" navigation item - Positioned before "Pack Management" - Uses `KeyRound` icon from lucide-react ## Features Implemented ### List Page (`/keys`) - **Display Columns:** - Reference (with key icon) - Name (human-readable) - Scope (color-coded badge) - Owner (identifier or "—") - Encrypted status (Yes/No with icons) - Created timestamp - Actions (Edit/Delete buttons) - **Search & Filtering:** - Real-time search by reference or name (client-side) - Scope filter dropdown (System, User, Pack, Action, Sensor) - Clear filters button - Shows filtered count - **Actions:** - Create Key button (top-right) - Edit button per row (opens modal) - Delete button per row (with confirmation) - **Pagination:** - 20 items per page - Previous/Next navigation - Page indicator ### Create Modal - **Required Fields:** - Reference (unique identifier with validation) - Name (human-readable description) - Value (format-dependent validation) - Scope (owner type) - **Value Format Options:** - **Text:** Plain text, can be encrypted - **JSON:** Validates JSON syntax, can be encrypted - **YAML:** Basic validation, can be encrypted - **Number:** Validates numeric, **cannot be encrypted** - **Integer:** Validates integer, **cannot be encrypted** - **Boolean:** Validates true/false, **cannot be encrypted** - **Encryption Rules:** - Text, JSON, YAML formats: Encryption checkbox enabled - Number, Integer, Boolean formats: Encryption checkbox disabled - Automatic encryption toggle disable for non-encryptable formats - Clear UI indication of encryption capability per format - **Scope Configuration:** - System: Global scope, no owner required - User (Identity): Optional owner identifier - Pack: Optional pack reference - Action: Optional action reference - Sensor: Optional sensor reference - **Validation:** - Reference format: alphanumeric, underscores, hyphens, dots only - Value format-specific validation - Required field checks - Error messages displayed in modal ### Edit Modal - **Features:** - Load existing key data - Display read-only metadata (reference, scope, owner) - Edit name and value - Show/Hide value toggle (Eye/EyeOff icons) - Encryption toggle - Warning when changing encryption status - Only sends changed fields to API - **Security:** - Value masked by default (can be toggled) - Clear indication of current encryption status - Warnings for encryption changes ## Technical Implementation ### API Integration Uses `SecretsService` from generated API client: - `listKeys({ page, perPage, ownerType, owner })` - List with pagination - `getKey({ ref })` - Get single key with decrypted value - `createKey({ requestBody })` - Create new key - `updateKey({ ref, requestBody })` - Update existing key - `deleteKey({ ref })` - Delete key ### State Management - React Query for server state and caching - Local state for UI (search, filters, modals) - Optimistic updates with cache invalidation - Proper loading and error states ### Scope (Owner Type) Badges Color-coded badges for quick identification: - **System**: Purple (bg-purple-100, text-purple-800) - **User (Identity)**: Blue (bg-blue-100, text-blue-800) - **Pack**: Green (bg-green-100, text-green-800) - **Action**: Yellow (bg-yellow-100, text-yellow-800) - **Sensor**: Indigo (bg-indigo-100, text-indigo-800) ### Encryption Indicators - **Encrypted**: EyeOff icon (green) + "Yes" text - **Not Encrypted**: Eye icon (gray) + "No" text ### Format Validation Logic ```typescript export type KeyFormat = "text" | "json" | "yaml" | "number" | "int" | "bool"; // Encryptable formats const canEncrypt = format === "text" || format === "json" || format === "yaml"; // Validation examples: - JSON: JSON.parse(value) - Number/Int: Number(value), isNaN check - Boolean: value.toLowerCase() === "true" || "false" ``` ## Design Patterns 1. **Consistent Modal Pattern:** - Fixed overlay with centered modal - Header with title and close button - Form with validation - Footer with Cancel and Submit buttons - Loading states during mutation 2. **Format-Aware UI:** - Dynamic textarea rows based on format - Placeholder text matches expected format - Validation errors specific to format - Auto-disable encryption for incompatible formats 3. **Security-First Approach:** - Encryption enabled by default for encryptable formats - Values masked in edit modal - Confirmation dialogs for destructive actions - Clear warnings when changing encryption 4. **Responsive Design:** - Grid layout for filters - Responsive table with horizontal scroll - Mobile-friendly pagination - Consistent with other pages (Events, Enforcements) ## User Flow Examples ### Creating a JSON Secret 1. Click "Create Key" button 2. Enter reference: `api_config` 3. Enter name: "API Configuration" 4. Select format: **JSON** (encryption checkbox enabled) 5. Enter value: `{"url": "https://api.example.com", "timeout": 30}` 6. Check "Encrypt value" (recommended) 7. Select scope: System 8. Click "Create Key" 9. ✅ Key created with encrypted JSON value ### Creating a Number Configuration 1. Click "Create Key" button 2. Enter reference: `max_retries` 3. Enter name: "Maximum Retry Attempts" 4. Select format: **Number** (encryption checkbox disabled) 5. Enter value: `3` 6. Note: Cannot encrypt (checkbox disabled and grayed out) 7. Select scope: System 8. Click "Create Key" 9. ✅ Key created with unencrypted numeric value ### Editing a Key 1. Click Edit button on any key row 2. Modal shows key metadata (read-only) 3. Modify name or value 4. Toggle show/hide value 5. Change encryption (warning displayed) 6. Click "Save Changes" 7. ✅ Key updated ## Known Limitations 1. **Format Field Client-Side Only:** - The "format" field is not stored in the backend database - Format is used for client-side validation only - All values are stored as text in the database - Future enhancement: Add `format` column to `key` table in backend 2. **Search Pagination:** - Search is client-side, so only searches current page - Consider adding server-side search parameter in future 3. **No Bulk Operations:** - Delete/update one key at a time - Could add multi-select for batch operations 4. **Value Masking:** - CSS-based masking may not work in all browsers - Consider more robust masking solution ## Security Considerations 1. **Encryption Enforcement:** - Only Text, JSON, YAML can be encrypted (per requirements) - Number, Integer, Boolean cannot be encrypted - UI enforces this with disabled checkbox 2. **Value Exposure:** - List view: Values are redacted (API behavior) - Detail view: Values are decrypted (requires explicit fetch) - Edit modal: Values are masked by default with toggle 3. **Access Control:** - Keys are scoped by owner type - Users can only access keys they have permissions for - Enforced at API level (frontend follows) ## Build Status ✅ TypeScript compilation successful ✅ Vite build successful (584.69 kB gzip: 152.21 kB) ✅ No compiler warnings or errors ✅ All routes registered correctly ## Testing Recommendations Manual testing should verify: 1. ✅ List page loads and displays keys 2. ✅ Search filters by reference and name 3. ✅ Scope filter works correctly 4. ✅ Create modal validates format-specific values 5. ✅ Encryption checkbox disabled for number/int/bool formats 6. ✅ JSON validation catches syntax errors 7. ✅ Boolean values must be "true" or "false" 8. ✅ Edit modal loads existing key data 9. ✅ Show/hide value toggle works 10. ✅ Delete confirms before deleting 11. ✅ Pagination functions properly 12. ✅ Empty states display correctly 13. ✅ Error states handle failures gracefully ## Future Enhancements 1. **Backend Format Field:** - Add `format` column to `key` table - Store format in database - Display format in list view - Validate format on backend 2. **Advanced Validation:** - More robust YAML parser - JSON schema validation - Custom format types 3. **Bulk Operations:** - Multi-select keys - Bulk delete - Bulk export/import 4. **Key Versioning:** - Track value history - Rollback to previous versions - Audit trail 5. **Server-Side Search:** - Add search parameter to API - Search across all pages - More efficient for large datasets 6. **Enhanced Security:** - Role-based key access - Key rotation policies - Expiration dates - Usage logging ## Documentation Updates Needed Consider updating: - `docs/api/api-secrets.md` - Document format field if added to backend - `docs/guides/secrets-management.md` - User guide for keys page - Add screenshots to documentation