Conversation
Co-authored-by: primeinc <4395149+primeinc@users.noreply.github.com>
Co-authored-by: primeinc <4395149+primeinc@users.noreply.github.com>
…ClientContext, interfaces) Co-authored-by: primeinc <4395149+primeinc@users.noreply.github.com>
This pull request introduces a comprehensive and security-hardened IPC (Inter-Process Communication) subsystem for the Files application, focusing on resource protection, authentication, and correctness. The changes include strict JSON-RPC 2.0 validation, encrypted token storage with epoch-based rotation, centralized method registry, rate limiting, lossy message queuing, and serialization of UI operations. Additionally, the configuration is now centralized and adjustable, and several new core components have been added to support robust remote control features. ### IPC Framework & Security Enhancements * Added strict JSON-RPC 2.0 validation and shape enforcement via the new `JsonRpcMessage` class, ensuring only valid requests and responses are processed. * Implemented DPAPI-encrypted token storage with epoch-based rotation in `ProtectedTokenStore`, invalidating sessions upon token rotation for enhanced security. * Introduced `ClientContext` for per-client state management, including token bucket rate limiting, lossy message queue with coalescing, and authentication epoch tracking. * Centralized method definitions and authorization policies in `RpcMethodRegistry`, supporting per-method payload limits and custom authorization. * Enforced all UI-affecting operations to be serialized using `UIOperationQueue`, requiring a dispatcher queue for thread safety. ### IPC Transport & Communication Layer * Defined the `IAppCommunicationService` interface for transport-agnostic communication services (WebSocket, Named Pipe), supporting request handling, broadcasting, and client responses. * Added runtime configuration via `IpcConfig`, allowing dynamic adjustment of message size caps, rate limits, and other resource controls. * Documented the architecture, supported methods, error codes, and configuration in `docs/remote-control/README.md`, including merge checklist and implementation status. ### Action & Data Model Support * Introduced `ActionRegistry` to manage allowed IPC actions and support extensibility for remote control operations. * Added `ItemDto` data model for representing file/folder metadata in IPC responses. ### Constants * Added a new `IpcSettings` section in `Constants.cs` to define default IPC limits and settings. * Minor code style fix in `Constants.cs` for consistency.
- Implemented App Notifications in `App.xaml.cs`. - Introduced `INavigationStateProvider` for navigation state. - Added `IpcPage` to `SettingsPageKind` and updated UI. - Registered IPC services in `AppLifecycleHelper.cs`. - Created `IpcViewModel` for managing IPC settings. - Updated `ShellIpcAdapter` to utilize navigation state. - Added `IpcPage.xaml` for IPC settings UI. - Updated resource files for new strings related to IPC.
- Modified `GroupAction.cs` to toggle `GroupDirection` based on current group direction. - Added `IIpcShellRegistry` interface for managing shell instances. - Introduced `IWindowResolver` interface to retrieve active window ID. - Created `IpcCoordinator` class for routing IPC requests and handling errors. - Implemented `IpcShellRegistry` for thread-safe management of IPC adapters. - Added `JsonRpcException` class for structured JSON-RPC error handling. - Introduced `NavigationStateFromShell` to manage navigation state. - Created `ShellIpcBootstrapper` for IPC adapter lifecycle management. - Implemented `WindowResolver` to return the main window ID. - Updated `AppLifecycleHelper.cs` to initialize IPC services and use `WebSocketAppCommunicationService`. - Enhanced `ShellIpcAdapter` with public methods for IPC coordination. - Updated `ModernShellPage.xaml.cs` to manage IPC bootstrapper lifecycle on page load/unload.
…ipc-hardened-final
Updated `ipc_test.py` to include a comprehensive IPC test suite with multiple test cases and a flexible command-line interface. Removed `test_ipc_edge_cases.py`, `test_ipc_multi.py`, and `test_simple.py` to consolidate testing into a single file. Improved error handling in `IpcCoordinator.cs` by sanitizing stack traces. Enhanced exception logging in `AppLifecycleHelper.cs` and added path validation in `ShellViewModel.cs` to prevent hangs on invalid paths.
Added `EphemeralPortAllocator` for TCP port allocation and `EphemeralTokenHelper` for generating unique tokens. Created `IpcRendezvousFile` to manage inter-process communication files. Refactored `NamedPipeAppCommunicationService` and `WebSocketAppCommunicationService` to utilize these new classes for improved connection handling and security. Added unit tests for the new functionality and updated project files for necessary references.
Improved the `IpcRendezvousFile` class to support model merging and stable token generation across services. Updated the update method to merge existing data in the rendezvous file, enhancing data integrity. Enhanced error handling and updated tests to align with the new token generation and file management behavior.
- Updated `ipc_test.py` for improved IPC configuration discovery, allowing automatic token and port discovery. - Introduced `test_multi_client.py` to validate simultaneous client connections using the same token. - Created `test_named_pipe.py` to test named pipe IPC functionality, including message sending and receiving. - Added `test_pipe_notifications.py` to validate notification handling over named pipes. - Implemented thread safety for pipe writing in `ClientContext.cs` with a new `BinaryWriter`. - Created `MultiTransportCommunicationService.cs` to manage both WebSocket and named pipe communications. - Enhanced `NamedPipeAppCommunicationService.cs` for better named pipe connection handling and security. - Modified `ProtectedTokenStore.cs` to include an environment variable for enabling IPC services in tests. - Updated dependency injection in `AppLifecycleHelper.cs` to support new communication services. - Renamed service variable in `IpcViewModel.cs` to reflect changes in the communication service.
Significantly refactored `ipc_test.py` for improved structure, error handling, and modular design. Introduced `test_ipc_unified.py` for unified testing of WebSocket and Named Pipe transports. Updated `test_multi_client.py` for multi-client connection validation. Enhanced `test_named_pipe.py` and `test_pipe_notifications.py` with better error handling and logging. Added `AppCommunicationServiceBase.cs` to centralize common IPC functionality, reducing duplication in `NamedPipeAppCommunicationService.cs` and `WebSocketAppCommunicationService.cs`. Overall improvements enhance maintainability and robustness of the IPC framework.
- Update ci.yml to work with primeinc fork - Add simplified ci-fork.yml that doesn't require secrets - Configure workflows to only run on PRs targeting main - Add workflow documentation README
XamlStyler formatting corrections to pass CI checks
Updated the SDK version in global.json from "8.0.119" to "9". This change reflects a transition to a newer major version, which may introduce new features, improvements, or breaking changes. Fix XAML formatting in SettingsDialog and IpcPage XamlStyler formatting corrections to pass CI checks
…inc/Files into feature/ipc-hardened-final
- Reformatted `using` statements in `AppCommunicationServiceBase.cs` for improved clarity. - Enhanced readability in `MultiTransportCommunicationService.cs` with better indentation and line breaks. - Updated comment terminology in `ShellIpcAdapter.cs` from "allowlist" to "allow list." - Clarified comments and modified tab ID generation logic in `ModernShellPage.xaml.cs` to indicate unique ID generation and improved window ID retrieval.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive and well-designed Inter-Process Communication (IPC) system. The architecture is robust, featuring support for both WebSocket and Named Pipe transports, strong security measures like DPAPI-encrypted token storage and per-user ACLs, and resilience features such as rate limiting and lossy message queues. The code is well-structured with clear separation of concerns between transport services, the central coordinator, and shell adapters. The addition of a unified Python test suite is also a great step towards ensuring correctness and parity between transports. My review has identified a couple of minor areas for improvement, mainly related to code cleanup and best practices in the test script. Overall, this is an excellent and significant contribution.
There was a problem hiding this comment.
Code Review
This is an impressive and substantial pull request that introduces a well-designed and robust IPC subsystem. The implementation demonstrates a strong focus on security, resource management, and correctness, with support for both WebSocket and Named Pipe transports. The addition of a comprehensive Python test suite and detailed documentation is excellent. My review includes a few minor suggestions to further improve code clarity and maintainability.
src/Files.App/Communication/NamedPipeAppCommunicationService.cs
Outdated
Show resolved
Hide resolved
- Added a new command for viewing pull requests in `settings.local.json`. - Enhanced message length validation in `NamedPipeAppCommunicationService.cs` to prevent integer overflow. - Updated string constants in `Constants.cs` for clarity and organization, replacing `MTP_DEVICE_PREFIX` with `EXTENDED_PATH_PREFIX` and adding `MTP_PREFIX`. - Improved path validation logic in `ShellIpcAdapter.cs` to include new constants. - Refactored checks for special path prefixes in `ShellViewModel.cs` to use defined constants, enhancing maintainability and readability.
- Updated `.gitignore` to include `FodyWeavers.xsd`. - Improved comments in `ClientContext.cs` for clarity on O(n) complexity. - Refactored stack trace sanitization in `IpcCoordinator.cs` to use a constant. - Enhanced error handling in `IpcRendezvousFile.cs` for file operations. - Added `StackTraceSanitizationMaxLength` constant in `Constants.cs`. - Refined exception handling in `AppLifecycleHelper.cs` for better diagnostics. - Introduced action handlers dictionary in `ShellIpcAdapter.cs` for extensible action management. - Simplified action execution logic in `ShellIpcAdapter.cs` using the new registry. - Modified cache cleanup logic in `ShellViewModel.cs` to use a deterministic threshold.
- Added new test methods in `UnifiedIpcTester` for listing shells and handling invalid actions. - Updated `ToggleDualPaneAction` to ensure proper pane management. - Removed `ActionRegistry` and introduced `IpcActionAdapter` to bridge IPC actions with the UI CommandManager. - Modified `ShellIpcAdapter` to utilize `IpcActionAdapter` for streamlined action execution. - Enhanced `IpcCoordinator` with a method for listing shells and targeted action execution. - Updated `ShellIpcBootstrapper` and dependency injection in `AppLifecycleHelper` to reflect the new action handling system. - Ensured `ModernShellPage` initializes IPC with the new adapter. - Overall improvements to IPC system robustness and error handling.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive IPC (Inter-Process Communication) system to the Files app, focusing on hardening security, improving resource management, and ensuring correctness. The changes include adding new files and modifying existing ones to implement features like JSON-RPC 2.0 validation, encrypted token storage, rate limiting, and UI operation serialization. The review focuses on identifying potential security vulnerabilities, areas for optimization, and maintainability concerns within the introduced code, particularly in the new communication and IPC-related files.
- Updated `ToggleDualPaneAction.cs` to disable action when multi-pane is unavailable due to narrow window. - Enhanced error logging in `AppCommunicationServiceBase.cs` to include exception messages and client IDs for better traceability. - Implemented an event-driven focus handling approach in `IpcActionAdapter.cs`, replacing the previous delay method. - Improved error handling in `IpcCoordinator.cs` with specific error codes and sanitized exception messages. - Clarified IPC enabling conditions in `ProtectedTokenStore.cs` with improved logging for debug mode. - Added a new settings prefix constant in `Constants.cs` for better organization. - Expanded documentation in `ShellIpcAdapter.cs` to clarify its purpose and functionality. - Ensured safe concurrent modifications in `ShellViewModel.cs` by taking snapshots of the path validation cache.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive and well-designed Inter-Process Communication (IPC) subsystem. The architecture is robust, featuring strong security measures like token-based authentication, per-user ACLs, and input sanitization. The implementation is clean, with good separation of concerns and helpful documentation in the code. The addition of a unified test suite is also a great step towards ensuring the feature's stability. I've identified a few areas for improvement, including a potential SDK version downgrade and some minor refinements in the test script and exception handling.
- Bump SDK version in `global.json` to 9.0.200 and change rollForward policy. - Remove unnecessary sleep in `test_ipc_unified.py` for UI updates. - Eliminate App Notification registration in `App.xaml.cs`. - Update SHA256 hash for `Files.App.Launcher.exe`. - Enhance security comments in `IpcActionAdapter.cs` regarding IPC action whitelist. - Remove `EnableIpcInDebugMode` property from `IpcConfig.cs`. - Split regex patterns for file path sanitization in `IpcCoordinator.cs`. - Modify `GetWindowInfo` to use Win32 API for accurate window data. - Simplify IPC enabling logic in `ProtectedTokenStore.cs`. - Add detailed comments on process termination in `AppLifecycleHelper.cs`. - Remove `ShellNavigationStateProvider` class, changing navigation state management. - Change Recycle Bin path check to be case-insensitive in `ShellViewModel.cs`.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This is an extensive and well-executed pull request that introduces a robust, secure, and well-documented IPC subsystem. The architecture is thoughtfully designed with clear separation of concerns, and security considerations are evident throughout the implementation, from DPAPI-encrypted token storage to detailed exception sanitization. The inclusion of a comprehensive Python test suite is commendable and adds a great deal of confidence in the solution's correctness. The changes to existing code also improve robustness and maintainability. I have a couple of minor suggestions regarding potential data loss from type casting, but overall this is an excellent contribution.
Enhance `GetActiveWindowId()` in `WindowResolver.cs` to include overflow protection when retrieving the window ID, logging a warning if the ID exceeds `uint.MaxValue`. Add a debug directive in `AppLifecycleHelper.cs` to prevent breaking in release builds unless a debugger is attached. Introduce XML documentation for the `IsPathValid` method in `ShellViewModel.cs` to clarify its purpose and behavior. Update window ID retrieval in `ModernShellPage.xaml.cs` to include overflow protection, ensuring robust handling and preventing silent data loss.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This is an impressive pull request that introduces a comprehensive and well-designed IPC subsystem. The architecture is robust, with strong considerations for security, performance, and correctness. The code is of high quality, with good separation of concerns and detailed comments explaining design decisions. The addition of a unified test script is also a great practice. My main feedback is a suggestion to refactor some duplicated code in the IpcActionAdapter to improve maintainability.
- Introduced a comprehensive security review process in `IpcActionAdapter.cs` for new actions, including threat analysis, validation, and logging requirements. - Added `SetFocusWithEventAsync` for efficient focus handling. - Improved stack trace sanitization in `IpcCoordinator.cs` for cleaner debug information. - Implemented `SanitizeExceptionMessage` and `SanitizeStackTrace` in `AppLifecycleHelper.cs` to prevent information disclosure. - Updated shell folder prefix checks in `ShellViewModel.cs` to be case-insensitive. - Added `resolve_threads.sh` script to automate GitHub review thread resolution.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This is a substantial and well-executed pull request that introduces a robust, secure, and feature-rich IPC subsystem. The architecture is thoughtfully designed with clear separation of concerns, and security considerations are evident throughout the implementation. The addition of a comprehensive test suite is also commendable. My review includes a high-severity fix for a potential test hang in the Python test script and a medium-severity suggestion for improving consistency in the C# code. Overall, excellent work.
| while time.time() - start_time < timeout: | ||
| # Read length | ||
| _, length_data = win32file.ReadFile(self.pipe_handle, 4) | ||
| length = struct.unpack('<I', length_data)[0] | ||
|
|
||
| # Read payload | ||
| _, payload_data = win32file.ReadFile(self.pipe_handle, length) | ||
| response = json.loads(payload_data.decode('utf-8')) | ||
|
|
||
| # Skip notifications | ||
| if response.get("IsNotification") or response.get("id") is None: | ||
| continue | ||
|
|
||
| if response.get("id") == msg_id: | ||
| if "error" in response and response["error"]: | ||
| raise RuntimeError(f"RPC error: {response['error']}") | ||
| return response.get("result") |
There was a problem hiding this comment.
The timeout implementation in this loop is not effective. The win32file.ReadFile call is blocking, which means if the server doesn't send any data, the test will hang indefinitely instead of timing out after 5 seconds. The while time.time() - start_time < timeout condition is only checked after a message is received.
To ensure the timeout is respected, you could use win32pipe.PeekNamedPipe to check for available data before calling ReadFile, and add a short sleep to prevent busy-waiting.
# Check if data is available before blocking to make the timeout effective
bytes_avail, _, _ = win32pipe.PeekNamedPipe(self.pipe_handle, 0)
if bytes_avail < 4: # Not enough data for length prefix
time.sleep(0.01) # Avoid busy-waiting
continue
# Read length
_, length_data = win32file.ReadFile(self.pipe_handle, 4)
if not length_data:
continue # Pipe might have been closed
length = struct.unpack('<I', length_data)[0]
# Read payload
_, payload_data = win32file.ReadFile(self.pipe_handle, length)
response = json.loads(payload_data.decode('utf-8'))
# Skip notifications
if response.get("IsNotification") or response.get("id") is None:
continue
if response.get("id") == msg_id:
if "error" in response and response["error"]:
raise RuntimeError(f"RPC error: {response['error']}")
return response.get("result")| /// <summary> | ||
| /// Sanitizes exception messages to remove sensitive information like file paths, tokens, and user data. | ||
| /// </summary> | ||
| private static string SanitizeExceptionMessage(string? message) | ||
| { | ||
| if (string.IsNullOrEmpty(message)) | ||
| return string.Empty; | ||
|
|
||
| // Remove Windows absolute paths (C:\Users\...) | ||
| message = System.Text.RegularExpressions.Regex.Replace(message, @"[A-Z]:\\[^""<>|]*", "[path]", System.Text.RegularExpressions.RegexOptions.IgnoreCase); | ||
|
|
||
| // Remove Unix-style paths (/home/user/...) | ||
| message = System.Text.RegularExpressions.Regex.Replace(message, @"\/[^""<>|]*\/[^""<>| ]+", "[path]"); | ||
|
|
||
| // Remove UNC paths (\\server\share\...) | ||
| message = System.Text.RegularExpressions.Regex.Replace(message, @"\\\\[^\\""<>|]+\\[^""<>|]*", "[network-path]"); | ||
|
|
||
| // Remove potential tokens/keys (base64-like strings) | ||
| message = System.Text.RegularExpressions.Regex.Replace(message, @"\b[A-Za-z0-9+/]{20,}={0,2}\b", "[token]"); | ||
|
|
||
| // Remove GUIDs | ||
| message = System.Text.RegularExpressions.Regex.Replace(message, @"\b[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\b", "[guid]"); | ||
|
|
||
| return message; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Sanitizes stack traces to remove sensitive file paths and system information. | ||
| /// </summary> | ||
| private static string SanitizeStackTrace(string? stackTrace) | ||
| { | ||
| if (string.IsNullOrEmpty(stackTrace)) | ||
| return string.Empty; | ||
|
|
||
| // Remove file paths with line numbers (e.g., C:\path\file.cs:line 123) | ||
| stackTrace = System.Text.RegularExpressions.Regex.Replace(stackTrace, @"[A-Z]:\\[^:""<>|]+\.cs:line \d+", "[source]:line [n]", System.Text.RegularExpressions.RegexOptions.IgnoreCase); | ||
|
|
||
| // Remove Unix paths with line numbers | ||
| stackTrace = System.Text.RegularExpressions.Regex.Replace(stackTrace, @"\/[^:""<>|]+\.cs:line \d+", "[source]:line [n]"); | ||
|
|
||
| // Remove remaining file paths | ||
| stackTrace = System.Text.RegularExpressions.Regex.Replace(stackTrace, @"[A-Z]:\\[^""<>|\s]+", "[path]", System.Text.RegularExpressions.RegexOptions.IgnoreCase); | ||
|
|
||
| // Truncate if too long to prevent log flooding | ||
| if (stackTrace.Length > 2000) | ||
| { | ||
| stackTrace = stackTrace.Substring(0, 2000) + "... [truncated]"; | ||
| } | ||
| Process.GetCurrentProcess().Kill(); | ||
|
|
||
| return stackTrace; | ||
| } |
There was a problem hiding this comment.
For consistency with IpcCoordinator.cs and for improved performance, consider converting AppLifecycleHelper to a partial class and using source-generated regexes for the sanitization logic in SanitizeExceptionMessage and SanitizeStackTrace. This avoids runtime regex compilation and keeps the implementation approach consistent across the codebase.
There was a problem hiding this comment.
Pull Request Overview
This PR implements a comprehensive hardened IPC (Inter-Process Communication) system for Files that enables remote control functionality via both WebSocket and Named Pipe transports. The system provides secure, rate-limited access to navigation, file operations, and UI actions through a JSON-RPC 2.0 API.
Key changes include:
- Complete IPC framework with dual transport support (WebSocket + Named Pipes)
- Security hardening with DPAPI token encryption, rate limiting, and strict validation
- Settings UI for remote control management with token rotation capabilities
Reviewed Changes
Copilot reviewed 50 out of 52 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
src/Files.App/Communication/* |
Core IPC framework including transport services, client management, and security |
src/Files.App/Views/Settings/IpcPage.* |
Settings UI for enabling/disabling remote control and managing tokens |
src/Files.App/ViewModels/Settings/IpcViewModel.cs |
ViewModel for IPC settings page with token management |
src/Files.App/ViewModels/ShellIpcAdapter.cs |
Adapter bridging IPC requests to shell operations with safety controls |
src/Files.App/Views/Shells/ModernShellPage.xaml.cs |
Integration of IPC bootstrapper with shell lifecycle |
tests/Files.InteractionTests/Ipc/EphemeralHelpersTests.cs |
Unit tests for IPC helper functions |
scripts/test_ipc_unified.py |
Comprehensive test suite for both transport protocols |
| [StructLayout(LayoutKind.Sequential)] | ||
| private struct RECT | ||
| { | ||
| public int Left; | ||
| public int Top; | ||
| public int Right; | ||
| public int Bottom; | ||
| } |
There was a problem hiding this comment.
The Win32 API declarations and RECT struct are duplicated functionality that likely exists elsewhere in the codebase. Consider extracting these to a shared Win32Interop class or reusing existing declarations to avoid code duplication.
| // or use scoped DI containers per shell instance. This would eliminate the need for focus manipulation. | ||
|
|
||
| // Local function to handle focus operations (DRY principle) | ||
| async Task SetFocusWithEventAsync(Microsoft.UI.Xaml.UIElement element, int timeoutMs, string operation, int elementId) |
There was a problem hiding this comment.
The local function SetFocusWithEventAsync is complex (35+ lines) and used twice. Consider extracting it to a private method or helper class to improve readability and testability.
| private bool DropOldestNotificationOfMethod(string targetMethod) | ||
| { | ||
| var tempQueue = new System.Collections.Generic.List<(string payload, string method)>(); | ||
| var dropped = false; | ||
|
|
||
| while (_notificationQueue.TryDequeue(out var item)) |
There was a problem hiding this comment.
The method recreates the entire queue using O(n) operations. While the comment acknowledges this trade-off, consider using a more efficient approach like tracking method counts separately and using a timestamp-based cleanup strategy to avoid frequent queue rebuilding.
| return string.Empty; | ||
|
|
||
| // Remove Windows absolute paths (C:\Users\...) | ||
| message = System.Text.RegularExpressions.Regex.Replace(message, @"[A-Z]:\\[^""<>|]*", "[path]", System.Text.RegularExpressions.RegexOptions.IgnoreCase); |
There was a problem hiding this comment.
Multiple Regex.Replace calls in sanitization methods should use compiled regex patterns or source-generated regex (available in .NET 7+) for better performance, especially since these methods may be called frequently during error handling.
| try | ||
| { | ||
| // Frame.SourcePageType throws COM exception if no page is loaded yet | ||
| return ItemDisplay?.SourcePageType ?? typeof(HomePage); | ||
| } | ||
| catch | ||
| { | ||
| // Frame not initialized yet, return a default | ||
| return typeof(HomePage); | ||
| } |
There was a problem hiding this comment.
The catch block should specify the expected exception type (COMException) rather than catching all exceptions. This prevents masking other unexpected exceptions that might indicate real bugs.
| try | ||
| { | ||
| File.WriteAllText(tmp, json); | ||
| // Try atomic move first (works if destination doesn't exist) | ||
| try | ||
| { | ||
| File.Move(tmp, path); | ||
| } | ||
| catch (IOException ex) | ||
| { | ||
| // Only handle "file exists" error, rethrow otherwise | ||
| const int ERROR_FILE_EXISTS = 0x50; // 80 decimal | ||
| const int ERROR_ALREADY_EXISTS = 0xB7; // 183 decimal | ||
| int errorCode = ex.HResult & 0xFFFF; |
There was a problem hiding this comment.
The Win32 error code constants should be extracted to a shared constants class rather than being redefined here. This improves maintainability and prevents magic numbers from being scattered throughout the codebase.
Resolved / Related Issues
To prevent extra work, all changes to the Files codebase must link to an approved issue marked as
Ready to build. Please insert the issue number following the hashtag with the issue number that this Pull Request resolves.Steps used to test these changes
Stability is a top priority for Files and all changes are required to go through testing before being merged into the repo. Please include a list of steps that you used to test this PR.