# System Patterns: hosts ## System Architecture ### Layered Architecture ``` ┌─────────────────────────────────────┐ │ TUI Layer │ ← User Interface (Textual) ├─────────────────────────────────────┤ │ Manager Layer │ ← Orchestration & Operations ├─────────────────────────────────────┤ │ Core Layer │ ← Business Logic ├─────────────────────────────────────┤ │ System Layer │ ← File I/O & DNS └─────────────────────────────────────┘ ``` ### Component Relationships #### TUI Layer (`src/hosts/main.py`) - ✅ **HostsManagerApp**: Complete Textual application with reactive state management - ✅ **Responsibilities**: User interaction, display logic, event handling, navigation - ✅ **Dependencies**: Core models and parser for data operations - ✅ **Implementation**: Two-pane layout with ListView and reactive updates #### Core Layer (`src/hosts/core/`) - ✅ **models.py**: Complete data structures (HostEntry, HostsFile) with validation - ✅ **parser.py**: Robust hosts file parsing, serialization, and file operations - ✅ **Responsibilities**: Pure business logic, data validation, file integrity - ✅ **Implementation**: Comprehensive validation and error handling #### System Layer (Implemented) - ✅ **File I/O**: Atomic file operations with backup support - ✅ **Permission checking**: Validation of file access permissions - 🔄 **DNS Resolution**: Planned for Phase 5 advanced features - 🔄 **Permission Management**: Sudo handling planned for Phase 3 edit mode ## Key Technical Decisions ### Data Model Design (Implemented) ```python @dataclass class HostEntry: ip_address: str hostnames: list[str] comment: str | None = None is_active: bool = True dns_name: str | None = None # For CNAME-like functionality # Implemented methods: def to_hosts_line(self) -> str @classmethod def from_hosts_line(cls, line: str) -> "HostEntry | None" def __post_init__(self) -> None # Validation @dataclass class HostsFile: entries: list[HostEntry] = field(default_factory=list) header_comments: list[str] = field(default_factory=list) footer_comments: list[str] = field(default_factory=list) # Implemented methods: def add_entry(self, entry: HostEntry) -> None def remove_entry(self, index: int) -> None def toggle_entry(self, index: int) -> None def get_active_entries(self) -> list[HostEntry] def get_inactive_entries(self) -> list[HostEntry] def sort_by_ip(self) -> None def sort_by_hostname(self) -> None def find_entries_by_hostname(self, hostname: str) -> list[HostEntry] def find_entries_by_ip(self, ip: str) -> list[HostEntry] ``` ### State Management (Implemented) - ✅ **Reactive state**: Using Textual's reactive attributes for UI updates - ✅ **Validation pipeline**: All data validated in models and parser - ✅ **File integrity**: Atomic operations preserve file structure - ✅ **Error handling**: Graceful degradation for all error conditions - 🔄 **Undo/Redo capability**: Planned for Phase 4 with command pattern - 🔄 **Dirty state tracking**: Will be implemented in Phase 3 edit mode ### Permission Model (Planned for Phase 3) ```python # Current implementation (read-only mode) class HostsManagerApp: edit_mode: reactive[bool] = reactive(False) # Always False in Phase 1 def update_status(self): mode = "Edit mode" if self.edit_mode else "Read-only mode" # Status bar shows current mode # Planned for Phase 3: class PermissionManager: def __init__(self): self.edit_mode = False self.sudo_acquired = False def enter_edit_mode(self) -> bool: # Request sudo permissions # Set edit_mode = True only if successful def exit_edit_mode(self): # Release sudo permissions # Set edit_mode = False ``` ## Design Patterns in Use ### Reactive Pattern (Implemented) ```python class HostsManagerApp(App): # Reactive attributes automatically update UI hosts_file: reactive[HostsFile] = reactive(HostsFile()) selected_entry_index: reactive[int] = reactive(0) edit_mode: reactive[bool] = reactive(False) def on_list_view_highlighted(self, event): # Automatic UI updates when selection changes self.selected_entry_index = event.list_view.index or 0 self.update_entry_details() ``` ### Data Validation Pattern (Implemented) ```python @dataclass class HostEntry: def __post_init__(self): # Comprehensive validation on creation if not self.ip_address or not self.hostnames: raise ValueError("IP address and hostnames required") # Validate IP address format try: ipaddress.ip_address(self.ip_address) except ValueError as e: raise ValueError(f"Invalid IP address: {e}") ``` ### Command Pattern (Planned for Phase 4) ```python # Will be implemented for undo/redo functionality class Command(ABC): @abstractmethod def execute(self) -> HostsFile: pass @abstractmethod def undo(self) -> HostsFile: pass ``` ### Factory Pattern (Implemented) ```python class HostsParser: def __init__(self, file_path: str = "/etc/hosts"): # Single parser handles all hosts file formats self.file_path = file_path ``` ## Critical Implementation Paths ### Application Startup (✅ Implemented) 1. ✅ **Initialize TUI**: Textual app with reactive state management 2. ✅ **Load hosts file**: Robust parsing with error handling 3. ✅ **Build UI**: Two-pane layout with ListView and details 4. ✅ **Enter main loop**: Smooth keyboard navigation and event handling 5. ✅ **Error handling**: Graceful degradation for file access issues ### Entry Navigation (✅ Implemented) 1. ✅ **Keyboard navigation**: Up/down arrows navigate entries 2. ✅ **Selection tracking**: Reactive updates to selected_entry_index 3. ✅ **Detail updates**: Automatic refresh of right pane details 4. ✅ **Position restoration**: Maintains cursor position on reload 5. ✅ **Visual feedback**: Clear indication of current selection ### File Operations (✅ Implemented) 1. ✅ **File parsing**: Comprehensive hosts file format support 2. ✅ **Comment preservation**: Maintains all comments and formatting 3. ✅ **Error handling**: Graceful handling of permission and format errors 4. ✅ **Validation**: Complete IP address and hostname validation 5. ✅ **Status feedback**: Clear user feedback for all operations ### Edit Mode Activation (🔄 Planned for Phase 3) 1. 🔄 **User triggers edit mode**: Keyboard shortcut implementation 2. 🔄 **Request sudo**: Secure password prompt 3. 🔄 **Validate permissions**: Ensure write access to `/etc/hosts` 4. 🔄 **Update UI state**: Enable edit operations and visual indicators 5. 🔄 **Maintain permissions**: Keep sudo active until explicit exit ### Entry Modification (🔄 Planned for Phase 3-4) 1. 🔄 **User action**: Toggle, reorder, or edit entry operations 2. 🔄 **Create command**: Command pattern for undo/redo support 3. 🔄 **Validate operation**: Real-time validation of changes 4. 🔄 **Execute command**: Apply changes to in-memory state 5. 🔄 **Update UI**: Immediate visual feedback 6. 🔄 **Track dirty state**: Mark file as needing save ### File Persistence (🔄 Planned for Phase 3) 1. 🔄 **User saves**: Explicit save command or auto-save option 2. 🔄 **Validate entire file**: Comprehensive syntax checking 3. 🔄 **Create backup**: Automatic backup before modifications 4. 🔄 **Write atomically**: Safe temporary file + rename operation 5. 🔄 **Verify write**: Confirm successful file write ### DNS Resolution Flow (🔄 Planned for Phase 5) 1. 🔄 **User requests resolution**: For entries with DNS names 2. 🔄 **Resolve hostname**: Async DNS resolution 3. 🔄 **Compare IPs**: Current IP vs resolved IP comparison 4. 🔄 **Present choice**: User dialog for IP selection 5. 🔄 **Update entry**: Apply user's choice with validation 6. 🔄 **Mark dirty**: Flag file for saving ## Error Handling Patterns ### Graceful Degradation - **Permission denied**: Fall back to read-only mode - **DNS resolution failure**: Show error but continue - **File corruption**: Load what's possible, warn user - **Network unavailable**: Disable DNS features ### User Feedback - **Status bar**: Show current mode and operation status - **Modal dialogs**: For errors requiring user attention - **Inline validation**: Real-time feedback on input - **Progress indicators**: For long-running operations ### Recovery Mechanisms - **Undo operations**: Allow reverting recent changes - **File restoration**: Restore from backup if available - **Safe mode**: Minimal functionality if errors occur - **Graceful exit**: Always attempt to save valid changes