-
Notifications
You must be signed in to change notification settings - Fork 2
API Interfaces Backend
Mohammad Nauman edited this page Jul 21, 2025
·
1 revision
New to the team? Start with the UX Engineer Onboarding Guide for a complete introduction.
This document provides comprehensive documentation for the Barqly Vault backend API interfaces available to the frontend. All interfaces are automatically generated from Rust types to ensure type safety and consistency.
- Single Source of Truth: All interfaces defined in Rust source code
- Automatic Generation: TypeScript definitions generated during build
- Type Safety: Frontend builds against generated interfaces
- Consistency: Documentation always matches implementation
- UI Interface: Only Tauri commands are public to the frontend
- Internal Modules: All other modules are private implementation details
- Clean Separation: Clear boundary between UI and backend logic
-
Unified Error Types: All commands use
CommandErrorwith structured information - User-Friendly Messages: Errors include recovery guidance and actionable information
- Programmatic Handling: Error codes enable client-side error handling
TypeScript definitions are automatically generated during build:
src-tauri/target/debug/build/barqly-vault-*/out/generated/types.ts
# Generate TypeScript definitions
cargo build --features generate-typesimport { invokeCommand, CommandError, ErrorCode } from './generated/types';
// Use the generated types for type safety
const result = await invokeCommand<GenerateKeyResponse>('generate_key', {
label: 'My Key',
passphrase: 'secure-passphrase'
});All commands follow a consistent response pattern:
// Success case
{ status: 'success'; data: T }
// Error case
{ status: 'error'; data: CommandError }interface CommandError {
code: ErrorCode; // Programmatic error code
message: string; // User-friendly message
details?: string; // Technical details for debugging
recovery_guidance?: string; // Suggested user actions
user_actionable: boolean; // Whether user can resolve
trace_id?: string; // Debugging trace ID
span_id?: string; // Debugging span ID
}interface ProgressUpdate {
operation_id: string;
progress: number; // 0.0 to 1.0
message: string; // Human-readable status
details?: ProgressDetails; // Operation-specific details
timestamp: string; // ISO 8601
estimated_time_remaining?: number; // seconds
}// Generate a new encryption keypair
generate_key(input: GenerateKeyInput): Promise<CommandResponse<GenerateKeyResponse>>
interface GenerateKeyInput {
label: string; // Key label/name
passphrase: string; // Encryption passphrase
}
interface GenerateKeyResponse {
public_key: string; // Public key for sharing
key_id: string; // Unique key identifier
saved_path: string; // Where key was saved
}// Validate passphrase strength
validate_passphrase(input: ValidatePassphraseInput): Promise<CommandResponse<ValidatePassphraseResponse>>
interface ValidatePassphraseInput {
passphrase: string;
}
interface ValidatePassphraseResponse {
is_valid: boolean;
message: string;
}// Encrypt files with a public key
encrypt_files(input: EncryptDataInput): Promise<CommandResponse<string>>
interface EncryptDataInput {
key_id: string; // Key to use for encryption
file_paths: string[]; // Files to encrypt
output_name?: string; // Optional output name
}// Decrypt files with a private key
decrypt_data(input: DecryptDataInput): Promise<CommandResponse<DecryptionResult>>
interface DecryptDataInput {
encrypted_file: string; // Encrypted file to decrypt
key_id: string; // Key to use for decryption
passphrase: string; // Key passphrase
output_dir: string; // Where to extract files
}
interface DecryptionResult {
extracted_files: string[]; // List of extracted files
output_dir: string; // Directory where files were extracted
manifest_verified: boolean; // Whether manifest was verified
}// Get status of encryption operation
get_encryption_status(input: GetEncryptionStatusInput): Promise<CommandResponse<EncryptionStatusResponse>>
interface GetEncryptionStatusInput {
operation_id: string;
}
interface EncryptionStatusResponse {
operation_id: string;
status: EncryptionStatus;
progress_percentage: number;
current_file?: string;
total_files: number;
processed_files: number;
total_size: number;
processed_size: number;
estimated_time_remaining?: number;
error_message?: string;
}
enum EncryptionStatus {
PENDING = 'Pending',
IN_PROGRESS = 'InProgress',
COMPLETED = 'Completed',
FAILED = 'Failed',
CANCELLED = 'Cancelled',
}// Get progress of any operation
get_progress(input: GetProgressInput): Promise<CommandResponse<GetProgressResponse>>
interface GetProgressInput {
operation_id: string;
}
interface GetProgressResponse {
operation_id: string;
progress: number;
message: string;
details?: ProgressDetails;
timestamp: string;
estimated_time_remaining?: number;
is_complete: boolean;
}// Verify extracted files against manifest
verify_manifest(input: VerifyManifestInput): Promise<CommandResponse<VerifyManifestResponse>>
interface VerifyManifestInput {
manifest_path: string; // Path to manifest file
extracted_files_dir: string; // Directory with extracted files
}
interface VerifyManifestResponse {
is_valid: boolean;
message: string;
file_count: number;
total_size: number;
}// List all available keys
list_keys(): Promise<CommandResponse<KeyMetadata[]>>
interface KeyMetadata {
label: string;
created_at: string;
public_key?: string;
}
// Delete a key
delete_key(key_id: string): Promise<CommandResponse<() => void>>// Get application configuration
get_config(): Promise<CommandResponse<AppConfig>>
interface AppConfig {
version: string;
default_key_label?: string;
remember_last_folder: boolean;
max_recent_files: number;
}
// Update application configuration
update_config(updates: AppConfigUpdate): Promise<CommandResponse<AppConfig>>
interface AppConfigUpdate {
default_key_label?: string;
remember_last_folder?: boolean;
max_recent_files?: number;
}// Select files or folders for encryption
select_files(selection_type: SelectionType): Promise<CommandResponse<FileSelection>>
enum SelectionType {
FILES = 'Files',
FOLDER = 'Folder',
}
interface FileSelection {
paths: string[];
total_size: number;
file_count: number;
selection_type: string;
}// Get information about a file
get_file_info(file_path: string): Promise<CommandResponse<FileInfo>>
interface FileInfo {
path: string;
name: string;
size: number;
is_file: boolean;
is_directory: boolean;
}// Create manifest for files
create_manifest(file_paths: string[]): Promise<CommandResponse<Manifest>>
interface Manifest {
version: string;
created_at: string;
files: FileInfo[];
total_size: number;
file_count: number;
}-
INVALID_INPUT- General input validation failure -
MISSING_PARAMETER- Required parameter not provided -
INVALID_PATH- Invalid file or directory path -
INVALID_KEY_LABEL- Invalid key label format -
WEAK_PASSPHRASE- Passphrase doesn't meet strength requirements -
INVALID_FILE_FORMAT- Unsupported file format -
FILE_TOO_LARGE- File exceeds size limits -
TOO_MANY_FILES- Too many files selected
-
PERMISSION_DENIED- Insufficient permissions -
PATH_NOT_ALLOWED- Path not allowed by security policy -
INSUFFICIENT_PERMISSIONS- More specific permission error -
READ_ONLY_FILE_SYSTEM- File system is read-only
-
KEY_NOT_FOUND- Encryption key not found -
FILE_NOT_FOUND- File doesn't exist -
DIRECTORY_NOT_FOUND- Directory doesn't exist -
OPERATION_NOT_FOUND- Operation ID not found
-
ENCRYPTION_FAILED- Encryption operation failed -
DECRYPTION_FAILED- Decryption operation failed -
STORAGE_FAILED- Storage operation failed -
ARCHIVE_CORRUPTED- Archive file is corrupted -
MANIFEST_INVALID- Manifest file is invalid -
INTEGRITY_CHECK_FAILED- Data integrity check failed -
CONCURRENT_OPERATION- Concurrent operation conflict
-
DISK_SPACE_INSUFFICIENT- Not enough disk space -
MEMORY_INSUFFICIENT- Not enough memory -
FILE_SYSTEM_ERROR- File system error -
NETWORK_ERROR- Network-related error
-
INVALID_KEY- Invalid encryption key -
WRONG_PASSPHRASE- Incorrect passphrase -
TAMPERED_DATA- Data has been tampered with -
UNAUTHORIZED_ACCESS- Unauthorized access attempt
-
INTERNAL_ERROR- Internal application error -
UNEXPECTED_ERROR- Unexpected error occurred -
CONFIGURATION_ERROR- Configuration error
import { invokeCommand, CommandError } from './generated/types';
async function encryptFiles() {
try {
// 1. Generate a key
const keyResult = await invokeCommand('generate_key', {
label: 'My Backup Key',
passphrase: 'secure-passphrase-123'
});
// 2. Select files
const selectionResult = await invokeCommand('select_files', 'Files');
// 3. Encrypt files
const encryptionResult = await invokeCommand('encrypt_files', {
key_id: keyResult.key_id,
file_paths: selectionResult.paths,
output_name: 'backup-encrypted'
});
console.log('Encryption completed:', encryptionResult);
} catch (error) {
if (error instanceof CommandError) {
if (error.isValidationError()) {
console.error('Validation error:', error.message);
} else if (error.isSecurityError()) {
console.error('Security error:', error.message);
} else {
console.error('Operation failed:', error.message);
}
}
}
}async function trackProgress(operationId: string) {
const interval = setInterval(async () => {
try {
const progress = await invokeCommand('get_progress', { operation_id: operationId });
console.log(`Progress: ${Math.round(progress.progress * 100)}%`);
console.log(`Message: ${progress.message}`);
if (progress.is_complete) {
clearInterval(interval);
console.log('Operation completed!');
}
} catch (error) {
clearInterval(interval);
console.error('Progress tracking failed:', error);
}
}, 1000);
}async function handleErrors() {
try {
const result = await invokeCommand('some_command', {});
return result;
} catch (error) {
if (error instanceof CommandError) {
switch (error.code) {
case 'INVALID_INPUT':
// Show validation error to user
showValidationError(error.message);
break;
case 'PERMISSION_DENIED':
// Request permissions from user
requestPermissions();
break;
case 'KEY_NOT_FOUND':
// Guide user to create or import key
showKeyNotFoundDialog();
break;
default:
// Show generic error
showError(error.message, error.recovery_guidance);
}
}
}
}- Import types from generated file for type safety
- Don't define interfaces manually in frontend
- Let TypeScript catch type mismatches at compile time
- Always wrap command calls in try-catch
- Use
CommandErrorclass for structured error handling - Provide user-friendly error messages
- Use progress updates for long-running operations
- Show progress bars and status messages
- Handle operation cancellation gracefully
- Validate user input before calling commands
- Use client-side validation for immediate feedback
- Let backend validation catch edge cases
- Never log sensitive data (passphrases, keys)
- Clear sensitive data from memory after use
- Use secure storage for configuration
- Define input/output types in Rust
- Add TypeScript equivalents in documentation
- Generate TypeScript definitions
- Update this documentation
- Test with frontend integration
- Update Rust types
- Regenerate TypeScript definitions
- Update frontend code to match new types
- Test backward compatibility
- Use appropriate error codes
- Provide user-friendly messages
- Include recovery guidance
- Test error scenarios
- All sensitive data is automatically zeroed from memory
- Passphrases use constant-time comparison
- Keys are stored encrypted at rest
- No sensitive data is logged
- All input is validated before processing
- Path traversal attempts are detected and blocked
- File size limits are enforced
- Malicious file types are rejected
- Commands only access allowed file system locations
- Key access requires proper authentication
- Operations are isolated and sandboxed
- Use streaming for large files
- Implement progress tracking
- Handle memory constraints gracefully
- Support operation cancellation
- Prevent conflicting operations
- Use operation IDs for tracking
- Implement proper cleanup
- Handle resource contention
- Test all command interfaces
- Verify error handling
- Test progress tracking
- Validate type safety
- Test complete workflows
- Verify data integrity
- Test error recovery
- Validate security measures
- Maintain backward compatibility
- Version API changes appropriately
- Document breaking changes
- Provide migration guides
- Keep documentation in sync with code
- Update examples for new features
- Maintain usage guidelines
- Document known issues
This document is automatically generated and maintained as part of the Barqly Vault development process. For questions or issues, please refer to the project documentation or create an issue in the repository.