fix: resolve Docker socket permissions and notification page routing

- Add runtime Docker socket permission detection in entrypoint
  - Detects socket GID and logs helpful deployment guidance
  - Provides three resolution options (root user, group-add, or chmod)
  - Non-intrusive: logs only, doesn't modify permissions

- Fix notification page routing mismatch
  - Move notifications route from /notifications to /settings/notifications
  - Add notifications tab to Settings page with Bell icon
  - Align navigation structure with route definitions

- Enhance Docker API error handling
  - Return 503 (not 500) when Docker daemon unavailable
  - Add DockerUnavailableError type for clear error distinction
  - Implement SSRF hardening (reject arbitrary host values)

- Improve security and testability
  - Move ProxyHost routes to protected auth group
  - Refactor Docker handler tests to use mocks
  - Simplify useDocker hook query enablement logic

Docker socket fix addresses deployment-level permission issue without
code changes. The 503 error correctly signals service unavailability
due to configuration, not application bugs.

Closes #XX (if applicable)
This commit is contained in:
GitHub Actions
2025-12-22 21:58:20 +00:00
parent ffa74d0968
commit baf822e084
14 changed files with 938 additions and 153 deletions

View File

@@ -81,6 +81,15 @@ describe('useDocker', () => {
expect(result.current.containers).toEqual([]);
});
it('does not fetch when both host and serverId are undefined', async () => {
const { result } = renderHook(() => useDocker(undefined, undefined), {
wrapper: createWrapper(),
});
expect(dockerApi.listContainers).not.toHaveBeenCalled();
expect(result.current.containers).toEqual([]);
});
it('returns empty array as default when no data', async () => {
vi.mocked(dockerApi.listContainers).mockResolvedValue([]);