From befd6da810a36f36766d0e8803a344d832e2c3df Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 10 Jul 2026 14:16:45 +0000 Subject: [PATCH 1/3] =?UTF-8?q?=EB=B3=B4=EC=95=88:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=A0=95=EB=B3=B4=20=EC=9C=A0=EC=B6=9C=20?= =?UTF-8?q?=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/sentinel.md | 4 ++++ .../src/bandscope_analysis/api.py | 16 ++++++++-------- services/analysis-engine/tests/test_api.py | 18 ++++++++---------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 466b2d87..c8838091 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -12,3 +12,7 @@ **Vulnerability:** Any project identifier that can reach a filesystem path join must be treated as untrusted, even when it is generated internally or passed through IPC lookup flows. **Learning:** Reject only dangerous path segments (`.` and `..`) and path separators (`/` and `\`) so the guard blocks traversal without rejecting ordinary identifiers such as `my..id`. **Prevention:** Keep project ID validation centralized before `base_root.join(project_id)`, and cover forward-slash, backslash, parent-component, and benign interior-dot cases in unit tests. +## 2026-07-10 - Exception Information Leakage Prevention +**Vulnerability:** The `_stem_separation_worker` exposed raw exception objects via `str(error)` in its queue messages, risking exposure of internal file paths and details. +**Learning:** In worker processes, errors must be caught and mapped to generic, user-safe messages before being sent over IPC mechanisms or queues to prevent internal structure exposure. +**Prevention:** Map exceptions (e.g. `FileNotFoundError`, `ValueError`) to static, safe string literals when passing error messages across boundaries. diff --git a/services/analysis-engine/src/bandscope_analysis/api.py b/services/analysis-engine/src/bandscope_analysis/api.py index 17cb1743..382cf8bc 100644 --- a/services/analysis-engine/src/bandscope_analysis/api.py +++ b/services/analysis-engine/src/bandscope_analysis/api.py @@ -859,14 +859,14 @@ def _stem_separation_worker( ) return result_queue.put(("ok", separation_result)) - except FileNotFoundError as error: - result_queue.put(("file_not_found", str(error))) - except ValueError as error: - result_queue.put(("value_error", str(error))) - except RuntimeError as error: - result_queue.put(("runtime_error", str(error))) - except Exception as error: - result_queue.put(("runtime_error", str(error))) + except FileNotFoundError: + result_queue.put(("file_not_found", "Audio source file not found.")) + except ValueError: + result_queue.put(("value_error", "Invalid audio source or stem request.")) + except RuntimeError: + result_queue.put(("runtime_error", "Audio separation process failed.")) + except Exception: + result_queue.put(("runtime_error", "Unexpected error during audio separation.")) def _multiprocessing_context() -> mp.context.BaseContext: diff --git a/services/analysis-engine/tests/test_api.py b/services/analysis-engine/tests/test_api.py index 8863e909..5176f339 100644 --- a/services/analysis-engine/tests/test_api.py +++ b/services/analysis-engine/tests/test_api.py @@ -872,18 +872,18 @@ def put(self, item: tuple[str, object]) -> None: self.items.append(item) cases = [ - (FileNotFoundError("missing"), "file_not_found"), - (ValueError("bad media"), "value_error"), - (RuntimeError("oom"), "runtime_error"), - (Exception("unexpected"), "runtime_error"), + (FileNotFoundError("missing"), "file_not_found", "Audio source file not found."), + (ValueError("bad media"), "value_error", "Invalid audio source or stem request."), + (RuntimeError("oom"), "runtime_error", "Audio separation process failed."), + (Exception("unexpected"), "runtime_error", "Unexpected error during audio separation."), ] - for error, expected_kind in cases: + for error, expected_kind, expected_message in cases: fake_queue = FakeQueue() with patch("bandscope_analysis.api.AudioStemSeparator") as separator_class: separator_class.return_value.separate.side_effect = error _stem_separation_worker("/tmp/audio.wav", fake_queue) - assert fake_queue.items == [(expected_kind, str(error))] + assert fake_queue.items == [(expected_kind, expected_message)] fake_queue = FakeQueue() with patch("bandscope_analysis.api.AudioStemSeparator") as separator_class: @@ -895,7 +895,7 @@ def put(self, item: tuple[str, object]) -> None: with patch("bandscope_analysis.api.AudioStemSeparator") as separator_class: separator_class.return_value.separate.return_value = {"stems": {}} _stem_separation_worker("/tmp/audio.wav", fake_queue, "/tmp/stems.npz") - assert fake_queue.items == [("runtime_error", "Stem separation returned invalid stems.")] + assert fake_queue.items == [("runtime_error", "Audio separation process failed.")] fake_queue = FakeQueue() with patch("bandscope_analysis.api.AudioStemSeparator") as separator_class: @@ -904,9 +904,7 @@ def put(self, item: tuple[str, object]) -> None: "stem_role_types": {"bass": "percussion"}, } _stem_separation_worker("/tmp/audio.wav", fake_queue, "/tmp/stems.npz") - assert fake_queue.items == [ - ("runtime_error", "Stem separation returned invalid stem role metadata.") - ] + assert fake_queue.items == [("runtime_error", "Audio separation process failed.")] def test_stem_separation_worker_writes_large_stems_to_file_envelope(tmp_path) -> None: From 8acc6b03fdfe2047914f82a8cdd6ef88419a5d61 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sat, 11 Jul 2026 08:59:42 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=EB=B3=B4=EC=95=88:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=A0=95=EB=B3=B4=20=EC=9C=A0=EC=B6=9C=20?= =?UTF-8?q?=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From d0e549d704a02d1a533377f9597152d0962f97bf Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Sun, 12 Jul 2026 12:14:58 +0000 Subject: [PATCH 3/3] chore: re-trigger CI --- .Jules/palette.md | 4 - .github/workflows/bandit.yml | 2 +- .github/workflows/build-baseline.yml | 90 +- .github/workflows/ci.yml | 4 +- .github/workflows/codeql.yml | 11 +- .github/workflows/dependency-review.yml | 30 + .github/workflows/ossf-scorecard.yml | 16 +- .github/workflows/release.yml | 2 +- .github/workflows/security-audit.yml | 2 +- .github/workflows/trivy.yml | 9 +- .gitignore | 1 - .jules/sentinel.md | 11 - .trivyignore | 6 +- AGENTS.md | 17 - CHANGELOG.md | 8 - CLAUDE.md | 75 - Cargo.lock | 586 --- Cargo.toml | 14 - README.md | 2 +- apps/desktop/.gitignore | 1 - apps/desktop/.storybook/main.ts | 23 - apps/desktop/.storybook/preview.ts | 14 - apps/desktop/core/Cargo.toml | 22 - apps/desktop/core/src/lib.rs | 1283 ------ apps/desktop/package.json | 12 +- apps/desktop/src-tauri/Cargo.lock | 152 +- apps/desktop/src-tauri/Cargo.toml | 2 - apps/desktop/src-tauri/build.rs | 6 - apps/desktop/src-tauri/capabilities/main.json | 8 +- .../src-tauri/gen/schemas/acl-manifests.json | 2 +- .../src-tauri/gen/schemas/capabilities.json | 2 +- .../src-tauri/gen/schemas/desktop-schema.json | 72 - .../src-tauri/gen/schemas/macOS-schema.json | 72 - .../src-tauri/gen/schemas/windows-schema.json | 2400 ----------- apps/desktop/src-tauri/osv-scanner.toml | 4 +- .../autogenerated/attach_score_pdf.toml | 11 - .../autogenerated/import_youtube_url.toml | 11 - .../autogenerated/load_project.toml | 11 - .../autogenerated/read_score_pdf.toml | 11 - .../autogenerated/remove_score_pdf.toml | 11 - .../autogenerated/save_project.toml | 11 - apps/desktop/src-tauri/src/main.rs | 981 ++++- apps/desktop/src/App.test.tsx | 99 +- apps/desktop/src/App.tsx | 274 +- apps/desktop/src/components/ui/accordion.tsx | 76 - apps/desktop/src/components/ui/breadcrumb.tsx | 107 - .../src/components/ui/button.stories.tsx | 22 - .../src/components/ui/checkbox.stories.tsx | 17 - apps/desktop/src/components/ui/checkbox.tsx | 39 - .../src/components/ui/dialog.stories.tsx | 39 - apps/desktop/src/components/ui/dialog.tsx | 120 - .../desktop/src/components/ui/in-page-nav.tsx | 67 - apps/desktop/src/components/ui/label.tsx | 21 - .../desktop/src/components/ui/radio-group.tsx | 50 - apps/desktop/src/components/ui/select.tsx | 128 - apps/desktop/src/components/ui/sonner.tsx | 33 - .../src/components/ui/step-indicator.tsx | 113 - apps/desktop/src/components/ui/switch.tsx | 34 - apps/desktop/src/components/ui/table.tsx | 122 - apps/desktop/src/components/ui/tooltip.tsx | 53 - .../src/components/ui/ui-added.test.tsx | 248 -- .../src/features/chords/index.test.tsx | 77 - apps/desktop/src/features/chords/index.tsx | 10 +- .../src/features/ranges/index.test.tsx | 88 - apps/desktop/src/features/ranges/index.tsx | 5 - .../src/features/score/ScoreView.test.tsx | 416 -- apps/desktop/src/features/score/ScoreView.tsx | 230 - .../src/features/score/ScoreViewer.test.tsx | 342 -- .../src/features/score/ScoreViewer.tsx | 317 -- apps/desktop/src/features/score/pdfjs.ts | 29 - .../src/features/score/scoreStorage.test.ts | 35 - .../src/features/score/scoreStorage.ts | 112 - .../src/features/workspace/RoleSwitcher.tsx | 2 +- .../src/features/workspace/SectionRoadmap.tsx | 6 +- .../src/features/workspace/Workspace.tsx | 75 +- apps/desktop/src/locales/en/common.json | 78 - apps/desktop/src/locales/ko/common.json | 78 - apps/desktop/src/setupTests.ts | 17 +- apps/desktop/vite.config.ts | 9 +- docs/security/dependency-policy.md | 3 +- eslint.config.js | 2 +- package-lock.json | 3778 ++--------------- package.json | 2 +- packages/shared-types/package.json | 2 +- packages/shared-types/src/index.ts | 43 +- packages/shared-types/test/index.test.ts | 27 - scripts/checks/verify_supply_chain.py | 38 +- .../release/build_tauri_bundle_with_retry.sh | 65 - services/analysis-engine/pyproject.toml | 5 +- .../src/bandscope_analysis/api.py | 65 +- .../src/bandscope_analysis/chords/__init__.py | 19 - .../src/bandscope_analysis/chords/capo.py | 189 +- .../chords/function_analyzer.py | 180 - .../bandscope_analysis/chords/key_detector.py | 153 - .../chords/section_harmony.py | 164 - .../chords/transposition.py | 332 -- .../bandscope_analysis/exports/__init__.py | 5 - .../src/bandscope_analysis/exports/chart.py | 259 -- .../src/bandscope_analysis/ranges/__init__.py | 8 - .../src/bandscope_analysis/ranges/analyzer.py | 99 +- .../src/bandscope_analysis/ranges/pressure.py | 220 - .../bandscope_analysis/roles/articulation.py | 161 - .../src/bandscope_analysis/roles/extractor.py | 4 + .../src/bandscope_analysis/roles/overlap.py | 131 - .../bandscope_analysis/sections/segmenter.py | 129 +- .../separation/audio_separator.py | 265 +- .../separation/separator.py | 4 + .../bandscope_analysis/temporal/__init__.py | 12 +- .../bandscope_analysis/temporal/analyzer.py | 41 +- .../src/bandscope_analysis/temporal/groove.py | 190 - .../src/bandscope_analysis/temporal/hits.py | 214 - .../bandscope_analysis/temporal/stability.py | 230 - .../bandscope_analysis/transcription/api.py | 172 +- services/analysis-engine/tests/test_api.py | 112 +- .../tests/test_articulation.py | 126 - .../tests/test_chart_export.py | 342 -- services/analysis-engine/tests/test_chords.py | 53 +- services/analysis-engine/tests/test_cli.py | 22 - .../tests/test_function_analyzer.py | 154 - services/analysis-engine/tests/test_groove.py | 127 - services/analysis-engine/tests/test_hits.py | 140 - .../tests/test_key_detector.py | 122 - .../tests/test_range_pressure.py | 173 - services/analysis-engine/tests/test_ranges.py | 90 +- .../tests/test_register_overlap.py | 151 - .../tests/test_section_harmony.py | 171 - .../analysis-engine/tests/test_segmenter.py | 56 +- .../analysis-engine/tests/test_separation.py | 498 +-- .../tests/test_supply_chain_policy.py | 69 +- .../tests/test_tempo_stability.py | 143 - .../analysis-engine/tests/test_temporal.py | 25 - .../tests/test_transcription.py | 231 +- .../tests/test_transposition.py | 174 - services/analysis-engine/uv.lock | 620 +-- 134 files changed, 2207 insertions(+), 18203 deletions(-) create mode 100644 .github/workflows/dependency-review.yml delete mode 100644 CLAUDE.md delete mode 100644 Cargo.lock delete mode 100644 Cargo.toml delete mode 100644 apps/desktop/.gitignore delete mode 100644 apps/desktop/.storybook/main.ts delete mode 100644 apps/desktop/.storybook/preview.ts delete mode 100644 apps/desktop/core/Cargo.toml delete mode 100644 apps/desktop/core/src/lib.rs delete mode 100644 apps/desktop/src-tauri/gen/schemas/windows-schema.json delete mode 100644 apps/desktop/src-tauri/permissions/autogenerated/attach_score_pdf.toml delete mode 100644 apps/desktop/src-tauri/permissions/autogenerated/import_youtube_url.toml delete mode 100644 apps/desktop/src-tauri/permissions/autogenerated/load_project.toml delete mode 100644 apps/desktop/src-tauri/permissions/autogenerated/read_score_pdf.toml delete mode 100644 apps/desktop/src-tauri/permissions/autogenerated/remove_score_pdf.toml delete mode 100644 apps/desktop/src-tauri/permissions/autogenerated/save_project.toml delete mode 100644 apps/desktop/src/components/ui/accordion.tsx delete mode 100644 apps/desktop/src/components/ui/breadcrumb.tsx delete mode 100644 apps/desktop/src/components/ui/button.stories.tsx delete mode 100644 apps/desktop/src/components/ui/checkbox.stories.tsx delete mode 100644 apps/desktop/src/components/ui/checkbox.tsx delete mode 100644 apps/desktop/src/components/ui/dialog.stories.tsx delete mode 100644 apps/desktop/src/components/ui/dialog.tsx delete mode 100644 apps/desktop/src/components/ui/in-page-nav.tsx delete mode 100644 apps/desktop/src/components/ui/label.tsx delete mode 100644 apps/desktop/src/components/ui/radio-group.tsx delete mode 100644 apps/desktop/src/components/ui/select.tsx delete mode 100644 apps/desktop/src/components/ui/sonner.tsx delete mode 100644 apps/desktop/src/components/ui/step-indicator.tsx delete mode 100644 apps/desktop/src/components/ui/switch.tsx delete mode 100644 apps/desktop/src/components/ui/table.tsx delete mode 100644 apps/desktop/src/components/ui/tooltip.tsx delete mode 100644 apps/desktop/src/components/ui/ui-added.test.tsx delete mode 100644 apps/desktop/src/features/chords/index.test.tsx delete mode 100644 apps/desktop/src/features/ranges/index.test.tsx delete mode 100644 apps/desktop/src/features/score/ScoreView.test.tsx delete mode 100644 apps/desktop/src/features/score/ScoreView.tsx delete mode 100644 apps/desktop/src/features/score/ScoreViewer.test.tsx delete mode 100644 apps/desktop/src/features/score/ScoreViewer.tsx delete mode 100644 apps/desktop/src/features/score/pdfjs.ts delete mode 100644 apps/desktop/src/features/score/scoreStorage.test.ts delete mode 100644 apps/desktop/src/features/score/scoreStorage.ts delete mode 100755 scripts/release/build_tauri_bundle_with_retry.sh delete mode 100644 services/analysis-engine/src/bandscope_analysis/chords/function_analyzer.py delete mode 100644 services/analysis-engine/src/bandscope_analysis/chords/key_detector.py delete mode 100644 services/analysis-engine/src/bandscope_analysis/chords/section_harmony.py delete mode 100644 services/analysis-engine/src/bandscope_analysis/chords/transposition.py delete mode 100644 services/analysis-engine/src/bandscope_analysis/exports/__init__.py delete mode 100644 services/analysis-engine/src/bandscope_analysis/exports/chart.py delete mode 100644 services/analysis-engine/src/bandscope_analysis/ranges/pressure.py delete mode 100644 services/analysis-engine/src/bandscope_analysis/roles/articulation.py delete mode 100644 services/analysis-engine/src/bandscope_analysis/roles/overlap.py delete mode 100644 services/analysis-engine/src/bandscope_analysis/temporal/groove.py delete mode 100644 services/analysis-engine/src/bandscope_analysis/temporal/hits.py delete mode 100644 services/analysis-engine/src/bandscope_analysis/temporal/stability.py delete mode 100644 services/analysis-engine/tests/test_articulation.py delete mode 100644 services/analysis-engine/tests/test_chart_export.py delete mode 100644 services/analysis-engine/tests/test_function_analyzer.py delete mode 100644 services/analysis-engine/tests/test_groove.py delete mode 100644 services/analysis-engine/tests/test_hits.py delete mode 100644 services/analysis-engine/tests/test_key_detector.py delete mode 100644 services/analysis-engine/tests/test_range_pressure.py delete mode 100644 services/analysis-engine/tests/test_register_overlap.py delete mode 100644 services/analysis-engine/tests/test_section_harmony.py delete mode 100644 services/analysis-engine/tests/test_tempo_stability.py delete mode 100644 services/analysis-engine/tests/test_transposition.py diff --git a/.Jules/palette.md b/.Jules/palette.md index 5c1c1698..8eaf4a5f 100644 --- a/.Jules/palette.md +++ b/.Jules/palette.md @@ -30,10 +30,6 @@ **Learning:** When native disabled buttons are wrapped in a focusable `span` to provide accessible tooltips, tests that previously found and clicked the `button` (by temporarily removing the `disabled` attribute) may fail or become overly complex. It is cleaner and more accurate to query the wrapper element (e.g. via its `title`) and fire events on it, reflecting the actual accessible DOM structure. **Action:** When testing UI components that wrap disabled buttons in a focusable span for accessibility (e.g., using a tooltip/title), use `screen.getByTitle(...)` to query the wrapper element for interactions like `fireEvent.click` rather than `screen.getByRole('button')`. -## 2024-05-24 - Avoid nesting native buttons with ARIA role button on wrappers -**Learning:** Adding `role="button"` to a `span` or `div` wrapper that contains a native ` - ); - })} +

- {t("localFirstDetail")} + Your rehearsal map stays on this device. Project files stay local. YouTube only leaves the app when you choose import.

- - + + Settings coming soon + + + + Help coming soon + +
-
- -
); } diff --git a/apps/desktop/src/components/ui/accordion.tsx b/apps/desktop/src/components/ui/accordion.tsx deleted file mode 100644 index 752e33a0..00000000 --- a/apps/desktop/src/components/ui/accordion.tsx +++ /dev/null @@ -1,76 +0,0 @@ -"use client" - -import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion" -import { ChevronDown } from "lucide-react" - -import { cn } from "@/lib/utils" - -/** Render a vertically stacked set of collapsible sections. */ -function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) { - return ( - - ) -} - -/** Render one collapsible accordion item. */ -function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) { - return ( - - ) -} - -/** Render the clickable header that toggles an item open or closed. */ -function AccordionTrigger({ - className, - children, - ...props -}: AccordionPrimitive.Trigger.Props) { - return ( - - svg]:rotate-180", - className - )} - {...props} - > - {children} - - - - ) -} - -/** Render the collapsible content panel of an item. */ -function AccordionContent({ - className, - children, - ...props -}: AccordionPrimitive.Panel.Props) { - return ( - -
{children}
-
- ) -} - -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/apps/desktop/src/components/ui/breadcrumb.tsx b/apps/desktop/src/components/ui/breadcrumb.tsx deleted file mode 100644 index 76061293..00000000 --- a/apps/desktop/src/components/ui/breadcrumb.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import * as React from "react" -import { ChevronRight, MoreHorizontal } from "lucide-react" - -import { cn } from "@/lib/utils" - -/** Render the breadcrumb navigation landmark. */ -function Breadcrumb(props: React.ComponentProps<"nav">) { - return