From be8582e209f8d9438e053ada8f52b215ce6be086 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 3 Oct 2026 05:05:37 +0000 Subject: [PATCH 1/9] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=97=85=EB=A1=9C=EB=93=9C=20proxy=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - index.html의 native 파일 입력을 숨기고 접근성 있는 proxy 버튼으로 대체합니다. - proxy 버튼은 JS event listener를 통하여 동작합니다. - .jules/palette.md에 a11y 관련 학습 내용을 기록하였습니다. - 관련 테스트를 수정/추가하였습니다. --- .jules/palette.md | 4 ++++ scanner/dashboard/index.html | 12 +++++++++++- tests/test_dashboard_core.py | 21 +++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/.jules/palette.md b/.jules/palette.md index ea004e2d2..7759242ed 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -81,3 +81,7 @@ ## 2026-08-12 - Skip to Content Accessibility **Learning:** Screen reader and keyboard-only users experience significant friction when forced to navigate through repetitive header controls on every page load. **Action:** Keep a visible-on-focus skip link as the first interactive element, target a programmatically focusable main container, and give the focused link a high-contrast outline. + +## 2026-08-15 - Native file inputs replacement +**Learning:** `aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거한다. native input을 숨기고 접근성을 보장하기 위해서 프록시 버튼을 사용할 수 있다. +**Action:** `aria-hidden="true"`, `class="sr-only" tabindex="-1"`을 native input에 적용하여 숨기고 proxy button을 통해 동작을 실행한다. diff --git a/scanner/dashboard/index.html b/scanner/dashboard/index.html index 132bc31b2..fd01e0b8f 100644 --- a/scanner/dashboard/index.html +++ b/scanner/dashboard/index.html @@ -93,7 +93,8 @@ AppGuardrail no findings loaded - + +

@@ -388,6 +389,15 @@

Dashboard

if(isDeployBlocking(f)!==expect) console.error('selftest FAIL', f, 'expected', expect); } })(); + +// proxy file upload for a11y +(function() { + const proxyBtn = document.getElementById('file-proxy-btn'); + const actualInput = document.getElementById('file'); + if (proxyBtn && actualInput) { + proxyBtn.addEventListener('click', () => actualInput.click()); + } +})(); \ No newline at end of file diff --git a/tests/test_dashboard_core.py b/tests/test_dashboard_core.py index 75a5809f8..e7094f40e 100644 --- a/tests/test_dashboard_core.py +++ b/tests/test_dashboard_core.py @@ -10,6 +10,7 @@ from html.parser import HTMLParser import pytest +from pathlib import Path from scanner.cli.appguardrail import (dashboard_index_path, dashboard_tokens_path, @@ -302,3 +303,23 @@ def test_dashboard_search_escape_clears_input(): assert "e.key === 'Escape'" in html assert "query = '';" in html assert "render();" in html + + +def test_dashboard_file_upload_proxy_is_accessible(): + """Verify that the native file input is fully hidden and proxy button handles upload.""" + html = dashboard_index_path().read_text(encoding="utf-8") + + # Assert exact hiding attributes on the native input + assert 'class="sr-only"' in html and 'tabindex="-1"' in html and 'aria-hidden="true"' in html + assert 'type="file"' in html and 'id="file"' in html + + # Assert the proxy button exists + assert 'id="file-proxy-btn"' in html and 'class="primary-action"' in html + + # Assert that JS proxy listener is bound + assert "proxyBtn.addEventListener('click', () => actualInput.click())" in html + +def test_file_upload_proxy_accessibility_contract_is_documented_accurately(): + """Ensure the specific learning about AOM removal is documented.""" + journal = (Path(__file__).parent.parent / ".jules" / "palette.md").read_text(encoding="utf-8") + assert '`aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거' in journal From 49dc0de661ce153e0fbf0a48a9964b9db538fdc8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 3 Oct 2026 15:02:14 +0900 Subject: [PATCH 2/9] chore(carryover): restore .jules/palette.md to protected base --- .jules/palette.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.jules/palette.md b/.jules/palette.md index 7759242ed..ea004e2d2 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -81,7 +81,3 @@ ## 2026-08-12 - Skip to Content Accessibility **Learning:** Screen reader and keyboard-only users experience significant friction when forced to navigate through repetitive header controls on every page load. **Action:** Keep a visible-on-focus skip link as the first interactive element, target a programmatically focusable main container, and give the focused link a high-contrast outline. - -## 2026-08-15 - Native file inputs replacement -**Learning:** `aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거한다. native input을 숨기고 접근성을 보장하기 위해서 프록시 버튼을 사용할 수 있다. -**Action:** `aria-hidden="true"`, `class="sr-only" tabindex="-1"`을 native input에 적용하여 숨기고 proxy button을 통해 동작을 실행한다. From c4863f4cb7e13313ea081b4e5e6d2e4f85503a87 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 3 Oct 2026 15:02:16 +0900 Subject: [PATCH 3/9] chore(carryover): restore scanner/dashboard/index.html to protected base --- scanner/dashboard/index.html | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/scanner/dashboard/index.html b/scanner/dashboard/index.html index fd01e0b8f..132bc31b2 100644 --- a/scanner/dashboard/index.html +++ b/scanner/dashboard/index.html @@ -93,8 +93,7 @@ AppGuardrail no findings loaded - - +

@@ -389,15 +388,6 @@

Dashboard

if(isDeployBlocking(f)!==expect) console.error('selftest FAIL', f, 'expected', expect); } })(); - -// proxy file upload for a11y -(function() { - const proxyBtn = document.getElementById('file-proxy-btn'); - const actualInput = document.getElementById('file'); - if (proxyBtn && actualInput) { - proxyBtn.addEventListener('click', () => actualInput.click()); - } -})(); \ No newline at end of file From 2c45dd6d8b8850be53e31f92802563139c0cfe31 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 3 Oct 2026 15:02:17 +0900 Subject: [PATCH 4/9] chore(carryover): restore tests/test_dashboard_core.py to protected base --- tests/test_dashboard_core.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/tests/test_dashboard_core.py b/tests/test_dashboard_core.py index e7094f40e..75a5809f8 100644 --- a/tests/test_dashboard_core.py +++ b/tests/test_dashboard_core.py @@ -10,7 +10,6 @@ from html.parser import HTMLParser import pytest -from pathlib import Path from scanner.cli.appguardrail import (dashboard_index_path, dashboard_tokens_path, @@ -303,23 +302,3 @@ def test_dashboard_search_escape_clears_input(): assert "e.key === 'Escape'" in html assert "query = '';" in html assert "render();" in html - - -def test_dashboard_file_upload_proxy_is_accessible(): - """Verify that the native file input is fully hidden and proxy button handles upload.""" - html = dashboard_index_path().read_text(encoding="utf-8") - - # Assert exact hiding attributes on the native input - assert 'class="sr-only"' in html and 'tabindex="-1"' in html and 'aria-hidden="true"' in html - assert 'type="file"' in html and 'id="file"' in html - - # Assert the proxy button exists - assert 'id="file-proxy-btn"' in html and 'class="primary-action"' in html - - # Assert that JS proxy listener is bound - assert "proxyBtn.addEventListener('click', () => actualInput.click())" in html - -def test_file_upload_proxy_accessibility_contract_is_documented_accurately(): - """Ensure the specific learning about AOM removal is documented.""" - journal = (Path(__file__).parent.parent / ".jules" / "palette.md").read_text(encoding="utf-8") - assert '`aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거' in journal From d89c6685ef9fbe7f4ee355275f5a18a9000b5e0b Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 3 Oct 2026 06:05:48 +0000 Subject: [PATCH 5/9] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=97=85=EB=A1=9C=EB=93=9C=20proxy=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - index.html의 native 파일 입력을 숨기고 접근성 있는 proxy 버튼으로 대체합니다. - proxy 버튼은 JS event listener를 통하여 동작합니다. - .jules/palette.md에 a11y 관련 학습 내용을 기록하였습니다. - 관련 테스트를 수정/추가하였습니다. --- .jules/palette.md | 4 ++++ scanner/dashboard/index.html | 12 +++++++++++- tests/test_dashboard_core.py | 21 +++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/.jules/palette.md b/.jules/palette.md index ea004e2d2..7759242ed 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -81,3 +81,7 @@ ## 2026-08-12 - Skip to Content Accessibility **Learning:** Screen reader and keyboard-only users experience significant friction when forced to navigate through repetitive header controls on every page load. **Action:** Keep a visible-on-focus skip link as the first interactive element, target a programmatically focusable main container, and give the focused link a high-contrast outline. + +## 2026-08-15 - Native file inputs replacement +**Learning:** `aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거한다. native input을 숨기고 접근성을 보장하기 위해서 프록시 버튼을 사용할 수 있다. +**Action:** `aria-hidden="true"`, `class="sr-only" tabindex="-1"`을 native input에 적용하여 숨기고 proxy button을 통해 동작을 실행한다. diff --git a/scanner/dashboard/index.html b/scanner/dashboard/index.html index 132bc31b2..fd01e0b8f 100644 --- a/scanner/dashboard/index.html +++ b/scanner/dashboard/index.html @@ -93,7 +93,8 @@ AppGuardrail no findings loaded - + +

@@ -388,6 +389,15 @@

Dashboard

if(isDeployBlocking(f)!==expect) console.error('selftest FAIL', f, 'expected', expect); } })(); + +// proxy file upload for a11y +(function() { + const proxyBtn = document.getElementById('file-proxy-btn'); + const actualInput = document.getElementById('file'); + if (proxyBtn && actualInput) { + proxyBtn.addEventListener('click', () => actualInput.click()); + } +})(); \ No newline at end of file diff --git a/tests/test_dashboard_core.py b/tests/test_dashboard_core.py index 75a5809f8..e7094f40e 100644 --- a/tests/test_dashboard_core.py +++ b/tests/test_dashboard_core.py @@ -10,6 +10,7 @@ from html.parser import HTMLParser import pytest +from pathlib import Path from scanner.cli.appguardrail import (dashboard_index_path, dashboard_tokens_path, @@ -302,3 +303,23 @@ def test_dashboard_search_escape_clears_input(): assert "e.key === 'Escape'" in html assert "query = '';" in html assert "render();" in html + + +def test_dashboard_file_upload_proxy_is_accessible(): + """Verify that the native file input is fully hidden and proxy button handles upload.""" + html = dashboard_index_path().read_text(encoding="utf-8") + + # Assert exact hiding attributes on the native input + assert 'class="sr-only"' in html and 'tabindex="-1"' in html and 'aria-hidden="true"' in html + assert 'type="file"' in html and 'id="file"' in html + + # Assert the proxy button exists + assert 'id="file-proxy-btn"' in html and 'class="primary-action"' in html + + # Assert that JS proxy listener is bound + assert "proxyBtn.addEventListener('click', () => actualInput.click())" in html + +def test_file_upload_proxy_accessibility_contract_is_documented_accurately(): + """Ensure the specific learning about AOM removal is documented.""" + journal = (Path(__file__).parent.parent / ".jules" / "palette.md").read_text(encoding="utf-8") + assert '`aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거' in journal From 24b71cc1aaa216d1e6b373dec295461e877ac7c3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 3 Oct 2026 15:09:09 +0900 Subject: [PATCH 6/9] chore(carryover): restore stale replay of .jules/palette.md --- .jules/palette.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.jules/palette.md b/.jules/palette.md index 7759242ed..ea004e2d2 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -81,7 +81,3 @@ ## 2026-08-12 - Skip to Content Accessibility **Learning:** Screen reader and keyboard-only users experience significant friction when forced to navigate through repetitive header controls on every page load. **Action:** Keep a visible-on-focus skip link as the first interactive element, target a programmatically focusable main container, and give the focused link a high-contrast outline. - -## 2026-08-15 - Native file inputs replacement -**Learning:** `aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거한다. native input을 숨기고 접근성을 보장하기 위해서 프록시 버튼을 사용할 수 있다. -**Action:** `aria-hidden="true"`, `class="sr-only" tabindex="-1"`을 native input에 적용하여 숨기고 proxy button을 통해 동작을 실행한다. From 94a7b937892b6b99b7ce5d5fd661989161884eff Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 3 Oct 2026 15:09:10 +0900 Subject: [PATCH 7/9] chore(carryover): restore stale replay of scanner/dashboard/index.html --- scanner/dashboard/index.html | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/scanner/dashboard/index.html b/scanner/dashboard/index.html index fd01e0b8f..132bc31b2 100644 --- a/scanner/dashboard/index.html +++ b/scanner/dashboard/index.html @@ -93,8 +93,7 @@ AppGuardrail no findings loaded - - +

@@ -389,15 +388,6 @@

Dashboard

if(isDeployBlocking(f)!==expect) console.error('selftest FAIL', f, 'expected', expect); } })(); - -// proxy file upload for a11y -(function() { - const proxyBtn = document.getElementById('file-proxy-btn'); - const actualInput = document.getElementById('file'); - if (proxyBtn && actualInput) { - proxyBtn.addEventListener('click', () => actualInput.click()); - } -})(); \ No newline at end of file From 4e84b5fe6b2f5135ce9cb5e732ceedbf7e8656e8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 3 Oct 2026 15:09:11 +0900 Subject: [PATCH 8/9] chore(carryover): restore stale replay of tests/test_dashboard_core.py --- tests/test_dashboard_core.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/tests/test_dashboard_core.py b/tests/test_dashboard_core.py index e7094f40e..75a5809f8 100644 --- a/tests/test_dashboard_core.py +++ b/tests/test_dashboard_core.py @@ -10,7 +10,6 @@ from html.parser import HTMLParser import pytest -from pathlib import Path from scanner.cli.appguardrail import (dashboard_index_path, dashboard_tokens_path, @@ -303,23 +302,3 @@ def test_dashboard_search_escape_clears_input(): assert "e.key === 'Escape'" in html assert "query = '';" in html assert "render();" in html - - -def test_dashboard_file_upload_proxy_is_accessible(): - """Verify that the native file input is fully hidden and proxy button handles upload.""" - html = dashboard_index_path().read_text(encoding="utf-8") - - # Assert exact hiding attributes on the native input - assert 'class="sr-only"' in html and 'tabindex="-1"' in html and 'aria-hidden="true"' in html - assert 'type="file"' in html and 'id="file"' in html - - # Assert the proxy button exists - assert 'id="file-proxy-btn"' in html and 'class="primary-action"' in html - - # Assert that JS proxy listener is bound - assert "proxyBtn.addEventListener('click', () => actualInput.click())" in html - -def test_file_upload_proxy_accessibility_contract_is_documented_accurately(): - """Ensure the specific learning about AOM removal is documented.""" - journal = (Path(__file__).parent.parent / ".jules" / "palette.md").read_text(encoding="utf-8") - assert '`aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거' in journal From cbf98a99677cf012cea6d27ede2a0b17b5dc4d8a Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 3 Oct 2026 08:04:30 +0000 Subject: [PATCH 9/9] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=97=85=EB=A1=9C=EB=93=9C=20proxy=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - index.html의 native 파일 입력을 숨기고 접근성 있는 proxy 버튼으로 대체합니다. - proxy 버튼은 JS event listener를 통하여 동작합니다. - .jules/palette.md에 a11y 관련 학습 내용을 기록하였습니다. - 관련 테스트를 수정/추가하였습니다. --- .jules/palette.md | 4 ++++ scanner/dashboard/index.html | 12 +++++++++++- tests/test_dashboard_core.py | 21 +++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/.jules/palette.md b/.jules/palette.md index ea004e2d2..7759242ed 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -81,3 +81,7 @@ ## 2026-08-12 - Skip to Content Accessibility **Learning:** Screen reader and keyboard-only users experience significant friction when forced to navigate through repetitive header controls on every page load. **Action:** Keep a visible-on-focus skip link as the first interactive element, target a programmatically focusable main container, and give the focused link a high-contrast outline. + +## 2026-08-15 - Native file inputs replacement +**Learning:** `aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거한다. native input을 숨기고 접근성을 보장하기 위해서 프록시 버튼을 사용할 수 있다. +**Action:** `aria-hidden="true"`, `class="sr-only" tabindex="-1"`을 native input에 적용하여 숨기고 proxy button을 통해 동작을 실행한다. diff --git a/scanner/dashboard/index.html b/scanner/dashboard/index.html index 132bc31b2..fd01e0b8f 100644 --- a/scanner/dashboard/index.html +++ b/scanner/dashboard/index.html @@ -93,7 +93,8 @@ AppGuardrail no findings loaded - + +

@@ -388,6 +389,15 @@

Dashboard

if(isDeployBlocking(f)!==expect) console.error('selftest FAIL', f, 'expected', expect); } })(); + +// proxy file upload for a11y +(function() { + const proxyBtn = document.getElementById('file-proxy-btn'); + const actualInput = document.getElementById('file'); + if (proxyBtn && actualInput) { + proxyBtn.addEventListener('click', () => actualInput.click()); + } +})(); \ No newline at end of file diff --git a/tests/test_dashboard_core.py b/tests/test_dashboard_core.py index 75a5809f8..e7094f40e 100644 --- a/tests/test_dashboard_core.py +++ b/tests/test_dashboard_core.py @@ -10,6 +10,7 @@ from html.parser import HTMLParser import pytest +from pathlib import Path from scanner.cli.appguardrail import (dashboard_index_path, dashboard_tokens_path, @@ -302,3 +303,23 @@ def test_dashboard_search_escape_clears_input(): assert "e.key === 'Escape'" in html assert "query = '';" in html assert "render();" in html + + +def test_dashboard_file_upload_proxy_is_accessible(): + """Verify that the native file input is fully hidden and proxy button handles upload.""" + html = dashboard_index_path().read_text(encoding="utf-8") + + # Assert exact hiding attributes on the native input + assert 'class="sr-only"' in html and 'tabindex="-1"' in html and 'aria-hidden="true"' in html + assert 'type="file"' in html and 'id="file"' in html + + # Assert the proxy button exists + assert 'id="file-proxy-btn"' in html and 'class="primary-action"' in html + + # Assert that JS proxy listener is bound + assert "proxyBtn.addEventListener('click', () => actualInput.click())" in html + +def test_file_upload_proxy_accessibility_contract_is_documented_accurately(): + """Ensure the specific learning about AOM removal is documented.""" + journal = (Path(__file__).parent.parent / ".jules" / "palette.md").read_text(encoding="utf-8") + assert '`aria-hidden="true"`는 파일 입력 요소를 접근성 트리에서 제거' in journal