-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
Description
📌 Parent Epic
#143 (Client-Side File Encryption for Zero-Knowledge Architecture)
🎯 Goal
Integrate file encryption into Share Target flow with progress indicators, error handling, and Secret selector UI.
📋 Implementation Tasks
1. Integration Tests (Write FIRST)
File: src/pages/ShareTarget.test.tsx (extend existing)
- Test: Encrypt files before adding to IndexedDB queue
- Test: Show encryption progress indicator
- Test: Handle encryption errors gracefully
- Test: Not expose encryption keys in console/errors
- Test: Update uploadState to 'encrypted' after encryption
- Test: Store encrypted blob in IndexedDB
- Test: Calculate checksums correctly
2. ShareTarget Component Updates
File: src/pages/ShareTarget.tsx (extend)
- Add Secret selector dropdown
- Add "Encrypt & Save" button
- Implement
handleEncryptAndSave()function- Get Secret's master key from API
- Derive file-specific key
- Calculate original checksum
- Encrypt file
- Calculate encrypted checksum
- Add to IndexedDB queue
- Add encryption progress indicators (per-file)
- Add error display for encryption failures
- Handle edge cases (no secret selected, crypto not supported)
3. Secret API Integration
File: src/services/secretApi.ts (new)
-
getSecretMasterKey(secretId: string): Promise<CryptoKey>- Fetch Secret from backend
- Extract encryption key
- Import as CryptoKey
- Error handling for API failures
4. FileQueue Hook Updates
File: src/hooks/useFileQueue.ts (extend)
- Extend
FileQueueEntrytype for encrypted blobs - Update
addToQueue()to accept encrypted data - Add
uploadStatefield ('pending', 'encrypting', 'encrypted', 'uploading', 'failed', 'completed')
5. UI Components
File: src/components/EncryptionProgress.tsx (new)
- Progress bar component
- Percentage display
- File name display
- Status indicator (encrypting, encrypted, failed)
File: src/components/SecretSelector.tsx (new)
- Dropdown for Secret selection
- Fetch Secrets from API
- Display Secret title + icon
- "Create new Secret" option
✅ Acceptance Criteria
- Files encrypted before IndexedDB storage
- Progress indicators work for each file
- Error handling graceful (user-friendly messages)
- No keys logged to console (security)
- Secret selector functional
- "Encrypt & Save" button works
- Multiple files handled correctly
- All tests passing (≥10 new tests)
- Code coverage ≥80% for new code
- TypeScript strict mode clean
- ESLint clean (no warnings)
- REUSE compliant (SPDX headers)
- Accessibility (a11y) compliant
🧪 Testing Strategy
describe('ShareTarget - File Encryption', () => {
it('should encrypt files before adding to IndexedDB queue', async () => {
const mockFile = new File(['secret data'], 'confidential.pdf');
render(<ShareTarget />);
await shareFiles([mockFile]);
const secretSelector = screen.getByLabelText('Select Secret');
fireEvent.change(secretSelector, { target: { value: 'secret-123' } });
const saveButton = screen.getByRole('button', { name: /encrypt & save/i });
fireEvent.click(saveButton);
await waitFor(() => {
expect(screen.getByText(/encrypted/i)).toBeInTheDocument();
});
const queueEntry = await fileQueueDB.get(mockFile.name);
expect(queueEntry.encryptedBlob).toBeDefined();
expect(queueEntry.uploadState).toBe('encrypted');
});
it('should show encryption progress indicator', async () => { ... });
it('should handle encryption errors gracefully', async () => { ... });
it('should not expose encryption keys in console/errors', async () => { ... });
});🔗 Dependencies
- Depends on: #TBD (Phase 1 - Crypto Utilities)
- Blocks: #TBD (Phase 3 - Upload Integration)
- Part of: Epic [EPIC] Client-Side File Encryption for Zero-Knowledge Architecture #143
📝 Technical Notes
Secret API Integration
// Fetch Secret and extract key
export async function getSecretMasterKey(secretId: string): Promise<CryptoKey> {
const response = await fetch(`/api/v1/secrets/${secretId}`, {
headers: getAuthHeaders()
});
if (!response.ok) throw new Error('Failed to fetch Secret');
const secret = await response.json();
// Import master key as CryptoKey
const keyData = base64ToArrayBuffer(secret.encryptionKey);
return crypto.subtle.importKey(
'raw',
keyData,
{ name: 'HKDF' },
false, // Non-extractable
['deriveBits', 'deriveKey']
);
}Progress Tracking
// Track encryption progress per file
const [encryptionProgress, setEncryptionProgress] = useState<Map<string, number>>(new Map());
// Update progress
setEncryptionProgress(prev => new Map(prev).set(file.name, 25)); // 25%
setEncryptionProgress(prev => new Map(prev).set(file.name, 50)); // 50%
setEncryptionProgress(prev => new Map(prev).set(file.name, 75)); // 75%
setEncryptionProgress(prev => new Map(prev).set(file.name, 100)); // 100%🎨 UI/UX Design
┌─────────────────────────────────────────┐
│ Share to SecPal │
├─────────────────────────────────────────┤
│ Files Shared: │
│ • confidential.pdf (1.2 MB) │
│ • medical-record.png (500 KB) │
│ │
│ Select Secret: │
│ ┌─────────────────────────────────┐ │
│ │ [Select a Secret...] ▼ │ │
│ └─────────────────────────────────┘ │
│ │
│ [🔐 Encrypt & Save to Secret] │
│ │
│ Encryption Progress: │
│ confidential.pdf: ████████░░ 75% │
│ medical-record.png: ██████████ 100% ✓ │
└─────────────────────────────────────────┘
🚀 Branch Strategy
# Create feature branch FROM Phase 1 branch
git checkout feat/crypto-utilities-phase1
git checkout -b feat/sharetarget-encryption-phase2
# Follow TDD cycle
git commit -S -m "test: add ShareTarget encryption integration tests (Phase 2.1)"
git commit -S -m "feat: add Secret selector component (Phase 2.2)"
git commit -S -m "feat: integrate encryption into ShareTarget (Phase 2.3)"
git commit -S -m "feat: add encryption progress indicators (Phase 2.4)"📏 PR Linking Instructions
When creating the PR for this sub-issue, use this in your PR description:
Fixes #TBD
Part of: #143
Depends on: #TBD (Phase 1)- Wait for Phase 1 PR to be merged before starting
- Do NOT use
Fixes #143- this is not the last sub-issue - PR size: ~400-500 LOC (UI + integration + tests)
Type: Sub-Issue (Phase 2/5)
Priority: High
Estimated Effort: 2 days
Sprint: Encryption Integration
Metadata
Metadata
Assignees
Labels
No labels
Type
Projects
Status
✅ Done