From 451054c559bf8da26d20fa1f4dacb315d4eb8d25 Mon Sep 17 00:00:00 2001 From: Fabricio Giglio <58532944+gigliof@users.noreply.github.com> Date: Wed, 6 May 2026 20:59:54 +0200 Subject: [PATCH] Add SECURITY.md, issue templates, update CONTRIBUTING --- .github/ISSUE_TEMPLATE/bug_report.yml | 87 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 5 ++ .github/ISSUE_TEMPLATE/feature_request.yml | 48 ++++++++++++ CONTRIBUTING.md | 14 ++-- README.md | 54 ++++++++------ SECURITY.md | 28 +++++++ 6 files changed, 207 insertions(+), 29 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 SECURITY.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..b6a1a04 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,87 @@ +name: Bug report +description: Something isn't working as expected +labels: [bug] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug. The more detail you provide, the faster it gets fixed. + + - type: dropdown + id: area + attributes: + label: Area + options: + - Falling notes / visualization + - Sheet music rendering + - Piano keyboard + - Audio / playback + - MIDI input (hardware keyboard) + - File import (MIDI) + - File import (MusicXML / MXL) + - File import (PDF) + - Practice tools (loop, speed trainer, wait mode, metronome) + - Settings / UI + - Other + validations: + required: true + + - type: textarea + id: description + attributes: + label: What happened? + description: A clear description of the bug. + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to reproduce + placeholder: | + 1. Import a MIDI file + 2. Enable wait mode + 3. ... + validations: + required: true + + - type: textarea + id: expected + attributes: + label: What did you expect? + validations: + required: true + + - type: dropdown + id: how + attributes: + label: How are you running the app? + options: + - pnpm dev (local) + - Docker + - Other + validations: + required: true + + - type: input + id: browser + attributes: + label: Browser + version + placeholder: "Chrome 124, Edge 123, ..." + validations: + required: true + + - type: input + id: os + attributes: + label: OS + placeholder: "macOS 14, Windows 11, ..." + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Console errors (if any) + description: Open DevTools → Console and paste anything relevant. + render: shell diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..8274652 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Security vulnerability + url: https://github.com/gigliof/bach-to-basics/security/advisories/new + about: Please report security issues privately via GitHub's vulnerability reporting. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..0fea341 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,48 @@ +name: Feature request +description: Suggest an idea or improvement +labels: [enhancement] +body: + - type: markdown + attributes: + value: | + Got an idea? Check the [roadmap](https://github.com/gigliof/bach-to-basics#roadmap) first — some features are already planned. + + - type: textarea + id: problem + attributes: + label: What problem does this solve? + description: Describe the use case or frustration behind the request. + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed solution + description: What would you like to see? Sketches, examples, or references to similar tools are welcome. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives you've considered + description: Any workarounds you're currently using? + + - type: dropdown + id: area + attributes: + label: Area + options: + - Falling notes / visualization + - Sheet music rendering + - Piano keyboard + - Audio / playback + - MIDI input + - File import / export + - Practice tools + - Settings / UI + - Performance + - Other + validations: + required: true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d0c2add..2956468 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,14 +31,18 @@ pnpm dev # starts frontend (5173) + backend (8000) concurrently ## Before opening a PR -1. `pnpm --filter frontend exec tsc --noEmit`: type check -2. `pnpm test`: frontend unit tests -3. If you touched the backend: `cd backend && python -m py_compile $(find . -name "*.py" -not -path "./.venv/*")` -4. Verify the dev server still boots cleanly (`pnpm dev`) +1. `pnpm lint`: ESLint (must pass with zero warnings) +2. `pnpm --filter frontend exec tsc --noEmit`: type check +3. `pnpm test`: frontend unit tests +4. If you touched the backend: `cd backend && python -m py_compile $(find . -name "*.py" -not -path "./.venv/*")` +5. Verify the dev server still boots cleanly (`pnpm dev`) + +The pre-commit hook runs ESLint + Prettier automatically on staged files, so formatting is handled for you. ## Reporting bugs Include: + - Browser + OS version - Whether you're running via `pnpm dev` or Docker - Steps to reproduce @@ -46,4 +50,4 @@ Include: ## Security -Found a vulnerability? Please don't open a public issue. Reach out via the contact info on the repo owner's GitHub profile. +Found a vulnerability? Please don't open a public issue. See [SECURITY.md](SECURITY.md) for how to report it privately. diff --git a/README.md b/README.md index 35854d1..132621a 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ A browser-based piano practice tool. Drop in a **MIDI file**, a **MusicXML score ![Bach to Basics demo](docs/demo.gif) -| Sheet music | All views | Settings | -|---|---|---| -| [![Sheet music](docs/screenshot-sheet.png)](docs/screenshot-sheet.png) | [![All views](docs/screenshot-all.png)](docs/screenshot-all.png) | [![Settings](docs/screenshot-settings.png)](docs/screenshot-settings.png) | +| Sheet music | All views | Settings | +| ----------------------------------------- | ------------------------------------- | ----------------------------------------- | +| ![Sheet music](docs/screenshot-sheet.png) | ![All views](docs/screenshot-all.png) | ![Settings](docs/screenshot-settings.png) | ## Features @@ -31,6 +31,7 @@ A browser-based piano practice tool. Drop in a **MIDI file**, a **MusicXML score Drag-and-drop anywhere on the window, or use the import button. > ⚠️ **A note on import accuracy.** Both PDF-to-MIDI (optical music recognition) and MIDI-to-sheet-music (notation reconstruction) are inherently lossy conversions. Expect some inconsistencies: +> > - **PDF imports** can mis-read notes, dynamics, ornaments, articulation, and voicing, especially with low-resolution scans, handwritten scores, or complex layouts. Audiveris is the best open-source OMR engine available, but no engine matches a careful human transcription. > - **MIDI imports** produce sheet music by re-deriving notation from raw note timings. MIDI doesn't encode key signatures, beaming, voicing, articulation, or enharmonic spelling, so the rendered sheet is an interpretation, not a faithful reproduction of the composer's original score. > @@ -67,16 +68,16 @@ Drag-and-drop anywhere on the window, or use the import button. ## Tech stack -| Layer | Technology | -|-------|-----------| -| Frontend | React 19, TypeScript, Vite, Tailwind CSS | -| Rendering | PixiJS 8 (falling notes + piano), AlphaTab (sheet music) | -| Audio | Tone.js (scheduling), smplr (sampled instruments), Web Audio API | -| MIDI input | WebMidi.js | -| State | Zustand | -| Backend | FastAPI (Python 3.11/3.12) | -| Music processing | music21, defusedxml | -| OMR (optional) | Audiveris (Java) | +| Layer | Technology | +| ---------------- | ---------------------------------------------------------------- | +| Frontend | React 19, TypeScript, Vite, Tailwind CSS | +| Rendering | PixiJS 8 (falling notes + piano), AlphaTab (sheet music) | +| Audio | Tone.js (scheduling), smplr (sampled instruments), Web Audio API | +| MIDI input | WebMidi.js | +| State | Zustand | +| Backend | FastAPI (Python 3.11/3.12) | +| Music processing | music21, defusedxml | +| OMR (optional) | Audiveris (Java) | ## Running the app @@ -129,16 +130,16 @@ Without the JAR, MIDI / MusicXML import still works, only PDF import is unavaila All backend settings come from environment variables. Copy `.env.example` to `.env` and edit. -| Variable | Default | Description | -|----------|---------|-------------| -| `ALLOWED_ORIGINS` | `http://localhost:5173` | Comma-separated list of allowed CORS origins | -| `BACKEND_API_KEY` | *(unset = open)* | When set, all requests must include `X-API-Key: ` | -| `REQUIRE_AUTH` | *(unset)* | Set to `1` to make the server refuse to start if `BACKEND_API_KEY` is not configured — useful for preventing accidental open deployments | -| `RATE_LIMIT_PER_MIN` | `60` | Max requests per IP per minute. `0` disables it | -| `HEAVY_RATE_LIMIT_PER_MIN` | `10` | Stricter limit applied to expensive endpoints (`/omr/`, `/youtube/`) | -| `TRUSTED_PROXY_IPS` | *(unset)* | Comma-separated IPs of trusted reverse proxies. When set, the real client IP is read from `X-Forwarded-For` instead of the connection address | -| `MUSIC21_TIMEOUT_S` | `60` | Hard timeout (seconds) for music21 conversions (MIDI-to-MusicXML, MusicXML-to-MIDI). Raise for very dense scores | -| `AUDIVERIS_TIMEOUT_S` | `120` | Hard timeout (seconds) for Audiveris OMR. Raise for large or multi-page PDFs | +| Variable | Default | Description | +| -------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| `ALLOWED_ORIGINS` | `http://localhost:5173` | Comma-separated list of allowed CORS origins | +| `BACKEND_API_KEY` | _(unset = open)_ | When set, all requests must include `X-API-Key: ` | +| `REQUIRE_AUTH` | _(unset)_ | Set to `1` to make the server refuse to start if `BACKEND_API_KEY` is not configured — useful for preventing accidental open deployments | +| `RATE_LIMIT_PER_MIN` | `60` | Max requests per IP per minute. `0` disables it | +| `HEAVY_RATE_LIMIT_PER_MIN` | `10` | Stricter limit applied to expensive endpoints (`/omr/`, `/youtube/`) | +| `TRUSTED_PROXY_IPS` | _(unset)_ | Comma-separated IPs of trusted reverse proxies. When set, the real client IP is read from `X-Forwarded-For` instead of the connection address | +| `MUSIC21_TIMEOUT_S` | `60` | Hard timeout (seconds) for music21 conversions (MIDI-to-MusicXML, MusicXML-to-MIDI). Raise for very dense scores | +| `AUDIVERIS_TIMEOUT_S` | `120` | Hard timeout (seconds) for Audiveris OMR. Raise for large or multi-page PDFs | > **Web MIDI requires HTTPS** in production. Plain `http://` only works on `localhost`. @@ -188,30 +189,35 @@ These will become user-facing in upcoming releases. PRs welcome. Sheet music doesn't render after loading a MIDI file The MIDI-to-MusicXML conversion runs on the backend. Check that the backend is up (`curl http://localhost:8000/health` should return OK) and look at the backend terminal for `music21` errors. Very dense scores can hit the `MUSIC21_TIMEOUT_S` (default 60s); raise it if needed. +
No sound from the on-screen piano The first interaction (any click) wakes the audio context. If you still hear nothing, open DevTools > Console and look for errors related to `AudioContext` or sample fetches from `danigb.github.io` / `gleitz.github.io`. Some corporate networks block these CDNs. +
"WebMIDI not supported" on Firefox or Safari Use Chrome, Edge, Brave, or Arc. Firefox and Safari haven't implemented Web MIDI. +
PDF import says "OMR engine not available" Either Audiveris isn't installed, or `audiveris.jar` isn't at `backend/bin/audiveris.jar`, or Java 17+ isn't on the PATH. See the PDF import section above. MIDI and MusicXML import are unaffected. +
Docker build fails on the frontend The frontend Dockerfile uses the repo root as build context to read `pnpm-workspace.yaml` and `shared/`. If you've moved or renamed those, update `docker-compose.yml`'s `build.context` accordingly. +
## Contributing @@ -225,4 +231,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md). Bug reports and PRs welcome. Third-party components (AlphaTab, music21, etc.) keep their own licenses, see [NOTICE](NOTICE) for the rundown. Notably: - **AlphaTab** is MPL-2.0 (per-file copyleft), fine for both open source and commercial use as long as you don't modify AlphaTab's own files. -- **Audiveris** is AGPL-3.0 and is *not* bundled, users download it separately, so this repo doesn't inherit AGPL obligations. +- **Audiveris** is AGPL-3.0 and is _not_ bundled, users download it separately, so this repo doesn't inherit AGPL obligations. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..ee758a2 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,28 @@ +# Security Policy + +## Scope + +Bach to Basics handles no user accounts, no personal data, and no financial information. It is a local music practice tool — the main attack surface is **file processing** (MIDI, MusicXML, PDF uploads) and the **FastAPI backend** when self-hosted. + +## What to report + +Worth reporting privately: + +- Remote code execution or sandbox escape via a crafted MIDI, MusicXML, or PDF file +- Server-side vulnerabilities in the FastAPI backend (path traversal, SSRF, etc.) +- Dependency vulnerabilities with a realistic exploit path + +Probably not a security issue (open a regular bug instead): + +- Unexpected UI behaviour caused by a malformed music file +- The app crashing or producing wrong output from bad input + +## Reporting + +Use **GitHub's private vulnerability reporting**: + +1. Go to the [Security tab](https://github.com/gigliof/bach-to-basics/security) of this repo +2. Click **"Report a vulnerability"** +3. Fill in the details — steps to reproduce, impact, any suggested fix + +You'll get a response within a few days. There's no formal embargo policy given the nature of this project, but please give a reasonable heads-up before going public.