From f7af02d5ddd1f468ac5f64c724ca514f5f976427 Mon Sep 17 00:00:00 2001 From: bradjin8 Date: Mon, 18 May 2026 10:25:57 -0400 Subject: [PATCH 1/6] feat: add pyproject.toml and comments on requiremnts.txt --- pyproject.toml | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 8 +++++ 2 files changed, 96 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..716cefb --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,88 @@ +[build-system] +requires = ["hatchling>=1.21"] +build-backend = "hatchling.build" + +[project] +name = "cppa-cursor-browser" +version = "0.1.0" +description = "Flask web application for browsing and exporting Cursor AI chat histories" +readme = "README.md" +license = { file = "LICENSE" } +authors = [{ name = "C++ Alliance", email = "admin@cppalliance.org" }] +requires-python = ">=3.11" + +# Runtime dependencies — bounded on both sides so CI resolves deterministically +# and breaking major releases are caught at install time rather than at runtime. +# Upper bounds are conservative: pin to current known-compatible major version. +# See also: requirements.txt (backward-compat alias; pyproject.toml is canonical). +dependencies = [ + "flask>=3.0,<4", + "fpdf2>=2.7,<3", +] + +[project.optional-dependencies] +# Desktop launcher (pywebview pulls in heavy system libs — GTK/Qt on Linux — +# so it is intentionally excluded from the web-server and CI installs). +desktop = ["pywebview>=5.0,<6"] + +# Development tooling: testing + type checking. +dev = [ + "pytest>=8,<9", + "mypy>=1.10,<2", +] + +[project.scripts] +# Primary CLI: export Cursor chat histories to Markdown / zip. +# Usage: cursor-chat-export [--since all|last] [--out DIR] [--no-zip] [--help] +cursor-chat-export = "scripts.export:main" + +# Desktop launcher (requires the [desktop] extra to be installed). +cursor-chat-browser = "launcher:main" + +[project.urls] +Repository = "https://github.com/cppalliance/cppa-cursor-browser" +Issues = "https://github.com/cppalliance/cppa-cursor-browser/issues" + +# ── Build configuration ──────────────────────────────────────────────────────── +# Flat layout (no src/ directory): enumerate every importable package and the +# two top-level application modules so the installed wheel has the same import +# surface as the repo checkout. +[tool.hatch.build.targets.wheel] +include = [ + "api/", + "models/", + "scripts/", + "services/", + "utils/", + "app.py", + "launcher.py", +] + +[tool.hatch.build.targets.sdist] +include = [ + "api/", + "models/", + "scripts/", + "services/", + "utils/", + "tests/", + "templates/", + "static/", + "app.py", + "launcher.py", + "requirements.txt", + "README.md", + "LICENSE", + "cursor-browser.spec", +] + +# ── Mypy ────────────────────────────────────────────────────────────────────── +# Mirrors the flags used in .github/workflows/tests.yml so local `mypy .` +# and CI produce identical results. +[tool.mypy] +ignore_missing_imports = true +no_strict_optional = true +pretty = true +# Exclude virtual-env and build artefact directories so that `mypy .` from the +# repo root matches CI behaviour (CI runs in a clean runner without a local venv). +exclude = ["venv/", "\\.venv/", "build/", "dist/"] diff --git a/requirements.txt b/requirements.txt index f15c00c..776f1df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,11 @@ +# Backward-compatibility shim — pyproject.toml is the canonical source of +# truth for dependencies. This file is retained so that +# legacy workflows running `pip install -r requirements.txt` keep working, +# but bounded version specifiers and the lock file live in pyproject.toml. +# +# Prefer: pip install -e . (installs the package + runtime deps) +# pip install -e ".[dev]" (+ pytest and mypy) +# pip install -e ".[desktop]" (+ pywebview for the GUI launcher) flask>=3.0 fpdf2>=2.7 pywebview>=5.0 From 51f7206060c03b07b66db411d9af26755f892ea6 Mon Sep 17 00:00:00 2001 From: bradjin8 Date: Mon, 18 May 2026 10:38:32 -0400 Subject: [PATCH 2/6] fix: add assets directories to project toml file. --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 716cefb..7e5041a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,8 @@ include = [ "scripts/", "services/", "utils/", + "templates/", + "static/", "app.py", "launcher.py", ] From 72d63ec69c0e47e00957bc32f76fd770fb7e0064 Mon Sep 17 00:00:00 2001 From: bradjin8 Date: Mon, 18 May 2026 10:40:31 -0400 Subject: [PATCH 3/6] fix: made pywebview for legacy install as optional. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 776f1df..72a7a98 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,4 @@ # pip install -e ".[desktop]" (+ pywebview for the GUI launcher) flask>=3.0 fpdf2>=2.7 -pywebview>=5.0 +# pywebview is desktop-only — install with: pip install -e ".[desktop]" From d9aa73ab593e4ade9150d25e1b6e35ed8e856a37 Mon Sep 17 00:00:00 2001 From: bradjin8 Date: Mon, 18 May 2026 13:30:42 -0400 Subject: [PATCH 4/6] fix: add an explicit constraint on Pillow to block known-vulnerable versions --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 7e5041a..1fa989c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,6 +18,9 @@ requires-python = ">=3.11" dependencies = [ "flask>=3.0,<4", "fpdf2>=2.7,<3", + # fpdf2 depends on Pillow; declare a floor + cap so resolvers cannot pick + # known-vulnerable Pillow releases while staying on Pillow 10.x. + "pillow>=10.0.0,<11", ] [project.optional-dependencies] From cebefcea20e2c567efdf4fb9fff28d3212dc74c9 Mon Sep 17 00:00:00 2001 From: bradjin8 Date: Mon, 18 May 2026 17:51:38 -0400 Subject: [PATCH 5/6] fix: review comments --- .github/workflows/tests.yml | 2 +- launcher.py | 10 ++++++++-- pyproject.toml | 9 ++++----- requirements.txt | 10 ++++------ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8c7f6a0..428228d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -27,7 +27,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - python-version: ["3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13"] steps: # Pinned to immutable commit SHAs (not @v4 / @v5) so a compromised tag # cannot silently swap the underlying action code on this CI runner. diff --git a/launcher.py b/launcher.py index 79b5ebb..fbfefac 100644 --- a/launcher.py +++ b/launcher.py @@ -5,12 +5,18 @@ directly in-process. """ -import webview - from app import create_app def main(): + try: + import webview + except ImportError: + raise SystemExit( + "pywebview is not installed. Install the [desktop] extra, e.g.\n" + ' pip install -e ".[desktop]"' + ) from None + app = create_app() webview.create_window( "Cursor Chat Browser", diff --git a/pyproject.toml b/pyproject.toml index 1fa989c..1a53edc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ description = "Flask web application for browsing and exporting Cursor AI chat h readme = "README.md" license = { file = "LICENSE" } authors = [{ name = "C++ Alliance", email = "admin@cppalliance.org" }] -requires-python = ">=3.11" +requires-python = ">=3.10" # Runtime dependencies — bounded on both sides so CI resolves deterministically # and breaking major releases are caught at install time rather than at runtime. @@ -18,9 +18,6 @@ requires-python = ">=3.11" dependencies = [ "flask>=3.0,<4", "fpdf2>=2.7,<3", - # fpdf2 depends on Pillow; declare a floor + cap so resolvers cannot pick - # known-vulnerable Pillow releases while staying on Pillow 10.x. - "pillow>=10.0.0,<11", ] [project.optional-dependencies] @@ -63,6 +60,7 @@ include = [ "launcher.py", ] +# sdist includes tests + ancillary files; wheel is runtime-only. [tool.hatch.build.targets.sdist] include = [ "api/", @@ -90,4 +88,5 @@ no_strict_optional = true pretty = true # Exclude virtual-env and build artefact directories so that `mypy .` from the # repo root matches CI behaviour (CI runs in a clean runner without a local venv). -exclude = ["venv/", "\\.venv/", "build/", "dist/"] +# Anchored regexes — unanchored `venv/` would match any path segment containing "venv/". +exclude = ["^venv/", "^\\.venv/", "^build/", "^dist/"] diff --git a/requirements.txt b/requirements.txt index 72a7a98..300b3ea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,9 @@ -# Backward-compatibility shim — pyproject.toml is the canonical source of -# truth for dependencies. This file is retained so that -# legacy workflows running `pip install -r requirements.txt` keep working, -# but bounded version specifiers and the lock file live in pyproject.toml. +# Backward-compatibility shim — mirrors [project.dependencies] in pyproject.toml. +# Keep version specifiers in sync when runtime deps change. # # Prefer: pip install -e . (installs the package + runtime deps) # pip install -e ".[dev]" (+ pytest and mypy) # pip install -e ".[desktop]" (+ pywebview for the GUI launcher) -flask>=3.0 -fpdf2>=2.7 +flask>=3.0,<4 +fpdf2>=2.7,<3 # pywebview is desktop-only — install with: pip install -e ".[desktop]" From 84366c4be407ca6d964fb1dd8512d55b651313d0 Mon Sep 17 00:00:00 2001 From: bradjin8 Date: Mon, 18 May 2026 17:58:54 -0400 Subject: [PATCH 6/6] fix: Add an explicit Pillow constraint to exclude known-vulnerable versions. --- pyproject.toml | 3 +++ requirements.txt | 1 + 2 files changed, 4 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 1a53edc..5f03f9f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,6 +18,9 @@ requires-python = ">=3.10" dependencies = [ "flask>=3.0,<4", "fpdf2>=2.7,<3", + # Security floor: fpdf2 allows Pillow>=8.3.2, so 9.x can still be resolved. + # CVE-2024-28219 (buffer overflow) fixed in Pillow 10.3.0 — https://nvd.nist.gov/vuln/detail/CVE-2024-28219 + "pillow>=10.3.0", ] [project.optional-dependencies] diff --git a/requirements.txt b/requirements.txt index 300b3ea..17e3882 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,5 @@ # pip install -e ".[desktop]" (+ pywebview for the GUI launcher) flask>=3.0,<4 fpdf2>=2.7,<3 +pillow>=10.3.0 # pywebview is desktop-only — install with: pip install -e ".[desktop]"