diff --git a/CHANGELOG.d/1131-dashboard-upload-proxy.md b/CHANGELOG.d/1131-dashboard-upload-proxy.md
new file mode 100644
index 00000000..46d896fe
--- /dev/null
+++ b/CHANGELOG.d/1131-dashboard-upload-proxy.md
@@ -0,0 +1,2 @@
+### Changed
+- (Dashboard) 헤더의 findings 파일 선택 컨트롤을 기존 `primary-action` 버튼으로 표시하고, 실제 파일 선택은 숨긴 네이티브 파일 입력이 계속 담당하도록 정리했습니다.
diff --git a/scanner/dashboard/index.html b/scanner/dashboard/index.html
index 132bc31b..078a72bd 100644
--- a/scanner/dashboard/index.html
+++ b/scanner/dashboard/index.html
@@ -93,7 +93,8 @@
AppGuardrailno findings loaded
-
+
+
@@ -324,7 +325,9 @@
Dashboard
render();
}
+const headerBrowseFindings = document.getElementById('header-browse-findings');
const fileInput = document.getElementById('file');
+headerBrowseFindings.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', () => {
const selectedFile = fileInput.files?.[0];
fileInput.value = '';
diff --git a/tests/test_dashboard_core.py b/tests/test_dashboard_core.py
index 75a5809f..be738615 100644
--- a/tests/test_dashboard_core.py
+++ b/tests/test_dashboard_core.py
@@ -77,7 +77,7 @@ def test_dashboard_rows_are_keyboard_accessible():
assert 'tabindex="0" role="button"' in html
assert 'title="View details for finding"' in html
assert "tbody tr:focus-visible" in html
- assert "aria-label=\"Upload findings file\"" in html
+ assert ">Upload findings file" in html
assert "aria-label=\"Search findings\"" in html
assert "aria-label=\"Filter by severity\"" in html
assert "tr.addEventListener('keydown'" in html
diff --git a/tests/test_dashboard_upload_proxy_contract.py b/tests/test_dashboard_upload_proxy_contract.py
new file mode 100644
index 00000000..06220881
--- /dev/null
+++ b/tests/test_dashboard_upload_proxy_contract.py
@@ -0,0 +1,20 @@
+"""Regression contract for the dashboard header findings-file picker proxy."""
+
+from scanner.cli.appguardrail import dashboard_index_path
+
+
+def test_header_upload_proxy_preserves_native_file_input_contract():
+ """Visible button activation delegates to the hidden native picker boundary."""
+ html = dashboard_index_path().read_text(encoding="utf-8")
+
+ assert '' in html
+ assert (
+ '' in html
+ )
+ assert "const headerBrowseFindings = document.getElementById('header-browse-findings');" in html
+ assert "const fileInput = document.getElementById('file');" in html
+ assert "headerBrowseFindings.addEventListener('click', () => fileInput.click());" in html
+ assert "const selectedFile = fileInput.files?.[0];" in html
+ assert "fileInput.value = '';" in html
+ assert "if(!selectedFile) return;" in html