diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..052f364 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,25 @@ +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + labels: + - "dependencies" + - "python" + commit-message: + prefix: "deps" + include: "scope" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + labels: + - "dependencies" + - "github-actions" + commit-message: + prefix: "ci" + include: "scope" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a9afb71 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,51 @@ +name: CI + +on: + pull_request: + branches: [main] + push: + branches: [main] + +permissions: + contents: read + +jobs: + test: + name: Python ${{ matrix.python-version }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ["3.10", "3.11", "3.12"] + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: "pip" + - name: Create venv + run: | + python -m venv .venv_BatLLM + - name: Install dependencies + run: | + . .venv_BatLLM/bin/activate + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + python -m pip install pytest pylint + - name: Compile sources + run: | + . .venv_BatLLM/bin/activate + python -m compileall . + - name: Run tests + run: | + . .venv_BatLLM/bin/activate + python run_tests.py + - name: Run pylint + if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12' }} + run: | + . .venv_BatLLM/bin/activate + pylint src run_batllm.py run_game_analyzer.py create_release_bundles.py create_homebrew_formula.py diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..e8a5060 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,20 @@ +name: Dependency review + +on: + pull_request: + branches: [main] + +permissions: + contents: read + pull-requests: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Review dependency changes + uses: actions/dependency-review-action@v4 + with: + fail-on-severity: high diff --git a/.github/workflows/pip-audit.yml b/.github/workflows/pip-audit.yml new file mode 100644 index 0000000..c515148 --- /dev/null +++ b/.github/workflows/pip-audit.yml @@ -0,0 +1,28 @@ +name: Python dependency audit + +on: + pull_request: + branches: [main] + push: + branches: [main] + schedule: + - cron: "17 4 * * 1" + +permissions: + contents: read + +jobs: + pip-audit: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: "pip" + - name: Audit requirements + uses: pypa/gh-action-pip-audit@v1.1.0 + with: + inputs: requirements.txt diff --git a/PR_BODY.md b/PR_BODY.md new file mode 100644 index 0000000..ebc8317 --- /dev/null +++ b/PR_BODY.md @@ -0,0 +1,38 @@ +## Summary + +This PR implements the confirmed high-confidence improvements from the BatLLM audit: + +- adds a repository security policy; +- adds Dependabot for Python and GitHub Actions dependencies; +- adds PR-time dependency review; +- adds scheduled and PR-time Python dependency auditing with `pip-audit`; +- adds a cross-platform Python CI matrix for Linux, macOS, and Windows; +- documents the single runtime-state invariant: installed application files are read-only and mutable state belongs under `BATLLM_HOME` or the platform app-data equivalent; +- adds a maintainer audit checklist for launchers, configuration, sessions, Ollama lifecycle, and release checks. + +## Rationale + +The audit found that BatLLM has several operational surfaces: source launchers, analyzer launchers, Homebrew packaging, release bundles, mutable configuration, saved sessions, and local Ollama orchestration. This makes repository hygiene and state-location consistency critical. + +This PR is deliberately additive. It avoids speculative refactors where source-level verification is required, but it establishes the CI/security/doc baseline needed before deeper changes such as entry-point consolidation, `pyproject.toml` migration, and state-path refactoring. + +## Verification + +Expected checks: + +```bash +python -m pip install --upgrade pip +python -m pip install -r requirements.txt +python run_tests.py +python -m compileall . +pylint src run_batllm.py run_game_analyzer.py create_release_bundles.py create_homebrew_formula.py +pip-audit -r requirements.txt +``` + +## Follow-up work + +- Convert runtime configuration writes to use `BATLLM_HOME` everywhere. +- Add migration logic for repository-relative historical config. +- Collapse launchers onto canonical installed entry points. +- Add `pyproject.toml` after confirming package/module names under `src/`. +- Add tests for path handling, missing Ollama, non-responsive Ollama, subprocess timeouts, and session migration. diff --git a/PR_TITLE.txt b/PR_TITLE.txt new file mode 100644 index 0000000..66765fe --- /dev/null +++ b/PR_TITLE.txt @@ -0,0 +1 @@ +Harden CI, dependency security, and runtime state documentation diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..938dfb6 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,22 @@ +# Security Policy + +## Supported versions + +Security fixes are provided for the current `main` branch and the most recent tagged release. + +## Reporting a vulnerability + +Report suspected vulnerabilities privately. Do not open a public issue containing exploit details, secrets, local paths, or reproduction data that may expose a user system. + +Include: + +- affected BatLLM version or commit; +- operating system and Python version; +- installation method; +- whether Ollama was installed system-wide, through Homebrew, or manually; +- minimal reproduction steps; +- relevant logs with secrets, local usernames, and paths redacted. + +## Security-relevant areas + +BatLLM interacts with a local Ollama service, reads and writes local configuration, stores sessions, and invokes launch scripts. Reports involving path traversal, unsafe subprocess use, unexpected writes outside the configured application directory, dependency compromise, or unintended disclosure of local files should be treated as security relevant. diff --git a/STATUS.md b/STATUS.md index 0180820..19c43ca 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,6 +1,6 @@ # BatLLM Status -Last updated: 2026-05-23 +Last updated: 2026-05-29 01:52 BatLLM is a Python/Kivy research, education, and game project for exploring AI-mediated play, prompt quality, LLM behaviour, and local-model workflows. The repository currently contains a playable local desktop game, a standalone read-only Game Analyzer, local Ollama lifecycle and model-management helpers routed through `modelito`, release-bundle tooling, Homebrew formula generation, generated API reference artefacts, and maintained user/developer documentation. @@ -12,7 +12,7 @@ The project should remain practical, critical, and educational. Destructive or e - Python: `>=3.10` and `<3.13` enforced by the launcher compatibility helper. - Main UI framework: Kivy `2.3.1` plus KivyMD `1.2.0`. -- LLM/runtime integration: Ollama through `modelito==1.4.0` and `ollama==0.5.3`. +- LLM/runtime integration: Ollama through `modelito==1.4.0` and `ollama>=0.5.11`. - Default shipped model: `smollm2` with first-run `last_served_model` intentionally blank. - Repository version: `0.3.6`. @@ -46,6 +46,7 @@ python run_batllm.py python run_game_analyzer.py ``` + ### Test Runner ```bash @@ -56,6 +57,20 @@ python run_tests.py full `run_tests.py full` requires `.venv_BatLLM` and may start/stop a real local Ollama service. Use it only when local Ollama state is safe to exercise. +## 2026-05-29: CI, Security, And Documentation Merge + +- Fast-forwarded the audit-driven branch into `main`; the repository now includes the CI, dependency-security, and documentation artefacts listed below. +- Updated `requirements.txt` and `packaging/homebrew/requirements.txt` to require the audited minimum versions: + - `ollama>=0.5.11` (fixes PYSEC-2025-145) + - `requests>=2.33.0` (fixes CVE-2026-25645) + - `pytest>=9.0.3` (fixes CVE-2025-71176) +- Added `.github/dependabot.yml`, `.github/workflows/dependency-review.yml`, and `.github/workflows/pip-audit.yml`; `.github/workflows/ci.yml` now creates `.venv_BatLLM` before installing dependencies and running tests. +- Added repository and docs-site security guidance in `SECURITY.md` and `docs/SECURITY.md`. +- Added `docs/STATE_AND_INSTALLATION.md` and `docs/MAINTAINER_AUDIT_CHECKLIST.md` for audit support and maintainer reference. +- Retained the audit bundle artefacts and helper script at the repository root for traceability: `batllm-audit-pr.patch`, `batllm-audit-pr-overlay.zip`, `batllm-pr-implementation/`, and `scripts/apply_audit_pr.sh`. +- Dependency Review workflow requires enabling the GitHub Dependency Graph in repository settings for full support. +- All other project state, architecture, and documentation remain as previously described. + ### Useful Environment Variables - `BATLLM_HOME`: redirects mutable config and saved-session data away from the repository or package install location. @@ -166,10 +181,12 @@ This status update followed a repository-wide audit on 2026-05-09. The audit ins - `VERSION`: active repository version (`0.3.6`). - `requirements.txt`: root development/runtime dependency pins. - `pytest.ini`: pytest path and discovery configuration. -- `.github/workflows/`: CI and Homebrew tap publication workflows. +- `.github/workflows/`: CI, dependency-review, pip-audit, multiplatform, and Homebrew tap publication workflows; `.github/dependabot.yml` tracks dependency updates. - `run_batllm.py`: main application launcher. - `run_game_analyzer.py`: standalone Game Analyzer launcher. - `run_tests.py`: cross-platform core/full test runner. +- `SECURITY.md` and `docs/SECURITY.md`: repository and docs-site security guidance. +- `docs/STATE_AND_INSTALLATION.md` and `docs/MAINTAINER_AUDIT_CHECKLIST.md`: audit support and maintainer checklist documents. - `src/`: application, game, analyzer, utility, and test source. - `src/app.kv` and `src/view/*.kv`: Kivy layout definitions. - `src/assets/`: images, prompts, sounds, and system instructions. @@ -181,6 +198,7 @@ This status update followed a repository-wide audit on 2026-05-09. The audit ins - `src/view/`: Kivy screen classes and UI helpers. - `docs/`: maintained user/developer docs, screenshots, diagrams, and generated API docs. - `packaging/homebrew/`: Homebrew distribution docs and pinned formula requirements. +- `batllm-audit-pr.patch`, `batllm-audit-pr-overlay.zip`, `batllm-pr-implementation/`, and `scripts/apply_audit_pr.sh`: audit bundle artefacts and helper script retained for traceability. - `tools/ollama_mock_server.py`: local mock server for Ollama integration smoke tests. ## Documentation State @@ -191,6 +209,9 @@ This status update followed a repository-wide audit on 2026-05-09. The audit ins - `docs/ROADMAP.md` describes 1.0 local desktop hardening and 2.0 networked-play direction using current `0.3.x` line wording. - `docs/RELEASE_CRITERIA_1_0.md` defines CI, reliability, UX, bundle, and documentation gates for a future 1.0 candidate. - `docs/CHANGELOG.md` keeps active unreleased notes on the `0.x` hold and draft 1.0 notes. +- `SECURITY.md` is the repository security policy, and `docs/SECURITY.md` mirrors that guidance for the published docs site. +- `docs/STATE_AND_INSTALLATION.md` summarises the current installation and repository state used by the audit bundle. +- `docs/MAINTAINER_AUDIT_CHECKLIST.md` records the maintainer checklist for the audit/security update. - `docs/index.html` is the static project showcase served by GitHub Pages from branch `main` and path `/docs`. - `docs/.nojekyll` keeps GitHub Pages from applying Jekyll processing to the static documentation tree. - `docs/FIRST_RUN_RELEASE_CHECKLIST.md` and `docs/UI_UNIFICATION_PLAN_1_0.md` remain release-preparation references. @@ -199,6 +220,11 @@ This status update followed a repository-wide audit on 2026-05-09. The audit ins ## Tests And Verification Status +### 2026-05-29 Merge Validation + +- No automated tests were rerun for the fast-forward merge to `main`; the branch only added dependency-floor, workflow, and documentation files. +- The validation record below remains the latest executed test evidence for the repository state. + ### Latest Commands Run For This Audit (2026-05-23 Bug Fix Audit) - Repository-wide source read: all Python files in `src/`, root launchers, `tools/`, `scripts/`, CI workflows, `requirements.txt`, `pytest.ini`, `.pylintrc`, and packaging files read and cross-referenced by three parallel agents. @@ -293,4 +319,4 @@ The previous status report recorded these successful checks from the same releas - Design the 2.0 server contract before adding web or repository-backed prompt/game sharing. - Add broader tests for malformed model responses, slow startup, missing models, session compatibility, analyzer edge cases, and packaged first-run behaviour. -Last updated: 2026-05-23 +Last updated: 2026-05-29 01:52 diff --git a/batllm-audit-pr-overlay.zip b/batllm-audit-pr-overlay.zip new file mode 100644 index 0000000..b365924 Binary files /dev/null and b/batllm-audit-pr-overlay.zip differ diff --git a/batllm-audit-pr.patch b/batllm-audit-pr.patch new file mode 100644 index 0000000..fd11e79 --- /dev/null +++ b/batllm-audit-pr.patch @@ -0,0 +1,311 @@ +diff --git a/.github/dependabot.yml b/.github/dependabot.yml +new file mode 100644 +index 0000000..0000000 +--- a/.github/dependabot.yml ++++ b/.github/dependabot.yml +@@ -0,0 +1,25 @@ ++version: 2 ++updates: ++ - package-ecosystem: "pip" ++ directory: "/" ++ schedule: ++ interval: "weekly" ++ open-pull-requests-limit: 5 ++ labels: ++ - "dependencies" ++ - "python" ++ commit-message: ++ prefix: "deps" ++ include: "scope" ++ ++ - package-ecosystem: "github-actions" ++ directory: "/" ++ schedule: ++ interval: "weekly" ++ open-pull-requests-limit: 5 ++ labels: ++ - "dependencies" ++ - "github-actions" ++ commit-message: ++ prefix: "ci" ++ include: "scope" +diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml +new file mode 100644 +index 0000000..0000000 +--- a/.github/workflows/ci.yml ++++ b/.github/workflows/ci.yml +@@ -0,0 +1,41 @@ ++name: CI ++ ++on: ++ pull_request: ++ branches: [main] ++ push: ++ branches: [main] ++ ++permissions: ++ contents: read ++ ++jobs: ++ test: ++ name: Python ${{ matrix.python-version }} on ${{ matrix.os }} ++ runs-on: ${{ matrix.os }} ++ strategy: ++ fail-fast: false ++ matrix: ++ os: [ubuntu-latest, macos-latest, windows-latest] ++ python-version: ["3.10", "3.11", "3.12"] ++ ++ steps: ++ - name: Checkout ++ uses: actions/checkout@v4 ++ - name: Set up Python ++ uses: actions/setup-python@v5 ++ with: ++ python-version: ${{ matrix.python-version }} ++ cache: "pip" ++ - name: Install dependencies ++ run: | ++ python -m pip install --upgrade pip ++ python -m pip install -r requirements.txt ++ python -m pip install pytest pylint ++ - name: Compile sources ++ run: python -m compileall . ++ - name: Run tests ++ run: python run_tests.py ++ - name: Run pylint ++ if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12' }} ++ run: pylint src run_batllm.py run_game_analyzer.py create_release_bundles.py create_homebrew_formula.py +diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml +new file mode 100644 +index 0000000..0000000 +--- a/.github/workflows/dependency-review.yml ++++ b/.github/workflows/dependency-review.yml +@@ -0,0 +1,20 @@ ++name: Dependency review ++ ++on: ++ pull_request: ++ branches: [main] ++ ++permissions: ++ contents: read ++ pull-requests: read ++ ++jobs: ++ dependency-review: ++ runs-on: ubuntu-latest ++ steps: ++ - name: Checkout ++ uses: actions/checkout@v4 ++ - name: Review dependency changes ++ uses: actions/dependency-review-action@v4 ++ with: ++ fail-on-severity: high +diff --git a/.github/workflows/pip-audit.yml b/.github/workflows/pip-audit.yml +new file mode 100644 +index 0000000..0000000 +--- a/.github/workflows/pip-audit.yml ++++ b/.github/workflows/pip-audit.yml +@@ -0,0 +1,28 @@ ++name: Python dependency audit ++ ++on: ++ pull_request: ++ branches: [main] ++ push: ++ branches: [main] ++ schedule: ++ - cron: "17 4 * * 1" ++ ++permissions: ++ contents: read ++ ++jobs: ++ pip-audit: ++ runs-on: ubuntu-latest ++ steps: ++ - name: Checkout ++ uses: actions/checkout@v4 ++ - name: Set up Python ++ uses: actions/setup-python@v5 ++ with: ++ python-version: "3.12" ++ cache: "pip" ++ - name: Audit requirements ++ uses: pypa/gh-action-pip-audit@v1.1.0 ++ with: ++ inputs: requirements.txt +diff --git a/PR_BODY.md b/PR_BODY.md +new file mode 100644 +index 0000000..0000000 +--- a/PR_BODY.md ++++ b/PR_BODY.md +@@ -0,0 +1,38 @@ ++## Summary ++ ++This PR implements the confirmed high-confidence improvements from the BatLLM audit: ++ ++- adds a repository security policy; ++- adds Dependabot for Python and GitHub Actions dependencies; ++- adds PR-time dependency review; ++- adds scheduled and PR-time Python dependency auditing with `pip-audit`; ++- adds a cross-platform Python CI matrix for Linux, macOS, and Windows; ++- documents the single runtime-state invariant: installed application files are read-only and mutable state belongs under `BATLLM_HOME` or the platform app-data equivalent; ++- adds a maintainer audit checklist for launchers, configuration, sessions, Ollama lifecycle, and release checks. ++ ++## Rationale ++ ++The audit found that BatLLM has several operational surfaces: source launchers, analyzer launchers, Homebrew packaging, release bundles, mutable configuration, saved sessions, and local Ollama orchestration. This makes repository hygiene and state-location consistency critical. ++ ++This PR is deliberately additive. It avoids speculative refactors where source-level verification is required, but it establishes the CI/security/doc baseline needed before deeper changes such as entry-point consolidation, `pyproject.toml` migration, and state-path refactoring. ++ ++## Verification ++ ++Expected checks: ++ ++```bash ++python -m pip install --upgrade pip ++python -m pip install -r requirements.txt ++python run_tests.py ++python -m compileall . ++pylint src run_batllm.py run_game_analyzer.py create_release_bundles.py create_homebrew_formula.py ++pip-audit -r requirements.txt ++``` ++ ++## Follow-up work ++ ++- Convert runtime configuration writes to use `BATLLM_HOME` everywhere. ++- Add migration logic for repository-relative historical config. ++- Collapse launchers onto canonical installed entry points. ++- Add `pyproject.toml` after confirming package/module names under `src/`. ++- Add tests for path handling, missing Ollama, non-responsive Ollama, subprocess timeouts, and session migration. +diff --git a/PR_TITLE.txt b/PR_TITLE.txt +new file mode 100644 +index 0000000..0000000 +--- a/PR_TITLE.txt ++++ b/PR_TITLE.txt +@@ -0,0 +1 @@ ++Harden CI, dependency security, and runtime state documentation +diff --git a/SECURITY.md b/SECURITY.md +new file mode 100644 +index 0000000..0000000 +--- a/SECURITY.md ++++ b/SECURITY.md +@@ -0,0 +1,22 @@ ++# Security Policy ++ ++## Supported versions ++ ++Security fixes are provided for the current `main` branch and the most recent tagged release. ++ ++## Reporting a vulnerability ++ ++Report suspected vulnerabilities privately. Do not open a public issue containing exploit details, secrets, local paths, or reproduction data that may expose a user system. ++ ++Include: ++ ++- affected BatLLM version or commit; ++- operating system and Python version; ++- installation method; ++- whether Ollama was installed system-wide, through Homebrew, or manually; ++- minimal reproduction steps; ++- relevant logs with secrets, local usernames, and paths redacted. ++ ++## Security-relevant areas ++ ++BatLLM interacts with a local Ollama service, reads and writes local configuration, stores sessions, and invokes launch scripts. Reports involving path traversal, unsafe subprocess use, unexpected writes outside the configured application directory, dependency compromise, or unintended disclosure of local files should be treated as security relevant. +diff --git a/docs/MAINTAINER_AUDIT_CHECKLIST.md b/docs/MAINTAINER_AUDIT_CHECKLIST.md +new file mode 100644 +index 0000000..0000000 +--- a/docs/MAINTAINER_AUDIT_CHECKLIST.md ++++ b/docs/MAINTAINER_AUDIT_CHECKLIST.md +@@ -0,0 +1,28 @@ ++# Maintainer audit checklist ++ ++Use this checklist before release or after changing launch, configuration, packaging, or Ollama lifecycle code. ++ ++## Functional checks ++ ++- `python run_tests.py` passes on Python 3.10, 3.11, and 3.12. ++- Application launch works from source checkout. ++- Analyzer launch works from source checkout. ++- Homebrew launcher and release-bundle launcher call the same canonical application entry path. ++- Changing model selection updates only the user state directory. ++- Saved sessions are written under the user state directory. ++- Legacy session files either migrate deterministically or fail with a clear compatibility message. ++ ++## Security and dependency checks ++ ++- `pip-audit -r requirements.txt` passes or accepted findings are documented. ++- Dependency Review passes on pull requests that change dependencies. ++- Dependabot pull requests are reviewed and merged or explicitly rejected. ++- No launcher uses untrusted shell interpolation. ++- Subprocess calls use explicit argument lists, bounded timeouts, and clear error propagation. ++ ++## Platform checks ++ ++- Linux, macOS, and Windows CI pass. ++- `BATLLM_HOME` works on all supported platforms. ++- Paths with spaces and non-ASCII characters are tested. ++- Missing Ollama, stopped Ollama, and non-responsive Ollama produce actionable errors. +diff --git a/docs/STATE_AND_INSTALLATION.md b/docs/STATE_AND_INSTALLATION.md +new file mode 100644 +index 0000000..0000000 +--- a/docs/STATE_AND_INSTALLATION.md ++++ b/docs/STATE_AND_INSTALLATION.md +@@ -0,0 +1,32 @@ ++# Installation channels and mutable state ++ ++BatLLM should use one state model across all installation channels. ++ ++## Invariant ++ ++Installed application files are read-only at runtime. User changes must not mutate the source tree, package installation directory, Homebrew cellar, application bundle, or release-bundle program directory. ++ ++Runtime state belongs in a per-user application directory. `BATLLM_HOME` overrides the default location and is the canonical mechanism for tests, portable bundles, and package-manager integrations. ++ ++## State categories ++ ++| Category | Mutable | Location | ++|---|---:|---| ++| Packaged defaults | No | repository/package data | ++| Effective configuration | Yes | `$BATLLM_HOME/config.yaml` or platform app-data equivalent | ++| Saved sessions | Yes | `$BATLLM_HOME/sessions/` | ++| Logs | Yes | `$BATLLM_HOME/logs/` | ++| Cache/temp files | Yes | `$BATLLM_HOME/cache/` | ++ ++## Required behaviour ++ ++- On first run, create the user state directory if it does not exist. ++- Copy packaged default configuration into the user state directory before applying user edits. ++- Treat repository-relative `src/configs/config.yaml` as a read-only default, not as runtime state. ++- Prefer atomic writes for configuration and saved sessions. ++- Do not write to the Homebrew cellar or any other package-manager-controlled directory. ++- Tests should set `BATLLM_HOME` to a temporary directory. ++ ++## Migration rule ++ ++If an older install has user-edited configuration in a repository-relative path, migrate it once into the user state directory and leave the original file untouched after migration. +diff --git a/scripts/apply_audit_pr.sh b/scripts/apply_audit_pr.sh +new file mode 100644 +index 0000000..0000000 +--- a/scripts/apply_audit_pr.sh ++++ b/scripts/apply_audit_pr.sh +@@ -0,0 +1,16 @@ ++#!/usr/bin/env bash ++set -euo pipefail ++ ++if [ ! -d .git ]; then ++ echo "Run this from the BatLLM repository root." >&2 ++ exit 1 ++fi ++ ++git checkout -b chore/audit-ci-security-state-docs ++cp -R .github docs SECURITY.md PR_TITLE.txt PR_BODY.md . ++git add . ++git commit -m "chore: add audit-driven CI security and state documentation" ++ ++echo "Branch created: chore/audit-ci-security-state-docs" ++echo "Open the PR with:" ++echo "gh pr create --title \"$(cat PR_TITLE.txt)\" --body-file PR_BODY.md" diff --git a/batllm-pr-implementation/.github/dependabot.yml b/batllm-pr-implementation/.github/dependabot.yml new file mode 100644 index 0000000..052f364 --- /dev/null +++ b/batllm-pr-implementation/.github/dependabot.yml @@ -0,0 +1,25 @@ +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + labels: + - "dependencies" + - "python" + commit-message: + prefix: "deps" + include: "scope" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + labels: + - "dependencies" + - "github-actions" + commit-message: + prefix: "ci" + include: "scope" diff --git a/batllm-pr-implementation/.github/workflows/ci.yml b/batllm-pr-implementation/.github/workflows/ci.yml new file mode 100644 index 0000000..8ef0035 --- /dev/null +++ b/batllm-pr-implementation/.github/workflows/ci.yml @@ -0,0 +1,41 @@ +name: CI + +on: + pull_request: + branches: [main] + push: + branches: [main] + +permissions: + contents: read + +jobs: + test: + name: Python ${{ matrix.python-version }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ["3.10", "3.11", "3.12"] + + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: "pip" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install -r requirements.txt + python -m pip install pytest pylint + - name: Compile sources + run: python -m compileall . + - name: Run tests + run: python run_tests.py + - name: Run pylint + if: ${{ matrix.os == 'ubuntu-latest' && matrix.python-version == '3.12' }} + run: pylint src run_batllm.py run_game_analyzer.py create_release_bundles.py create_homebrew_formula.py diff --git a/batllm-pr-implementation/.github/workflows/dependency-review.yml b/batllm-pr-implementation/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..e8a5060 --- /dev/null +++ b/batllm-pr-implementation/.github/workflows/dependency-review.yml @@ -0,0 +1,20 @@ +name: Dependency review + +on: + pull_request: + branches: [main] + +permissions: + contents: read + pull-requests: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Review dependency changes + uses: actions/dependency-review-action@v4 + with: + fail-on-severity: high diff --git a/batllm-pr-implementation/.github/workflows/pip-audit.yml b/batllm-pr-implementation/.github/workflows/pip-audit.yml new file mode 100644 index 0000000..c515148 --- /dev/null +++ b/batllm-pr-implementation/.github/workflows/pip-audit.yml @@ -0,0 +1,28 @@ +name: Python dependency audit + +on: + pull_request: + branches: [main] + push: + branches: [main] + schedule: + - cron: "17 4 * * 1" + +permissions: + contents: read + +jobs: + pip-audit: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: "pip" + - name: Audit requirements + uses: pypa/gh-action-pip-audit@v1.1.0 + with: + inputs: requirements.txt diff --git a/batllm-pr-implementation/PR_BODY.md b/batllm-pr-implementation/PR_BODY.md new file mode 100644 index 0000000..ebc8317 --- /dev/null +++ b/batllm-pr-implementation/PR_BODY.md @@ -0,0 +1,38 @@ +## Summary + +This PR implements the confirmed high-confidence improvements from the BatLLM audit: + +- adds a repository security policy; +- adds Dependabot for Python and GitHub Actions dependencies; +- adds PR-time dependency review; +- adds scheduled and PR-time Python dependency auditing with `pip-audit`; +- adds a cross-platform Python CI matrix for Linux, macOS, and Windows; +- documents the single runtime-state invariant: installed application files are read-only and mutable state belongs under `BATLLM_HOME` or the platform app-data equivalent; +- adds a maintainer audit checklist for launchers, configuration, sessions, Ollama lifecycle, and release checks. + +## Rationale + +The audit found that BatLLM has several operational surfaces: source launchers, analyzer launchers, Homebrew packaging, release bundles, mutable configuration, saved sessions, and local Ollama orchestration. This makes repository hygiene and state-location consistency critical. + +This PR is deliberately additive. It avoids speculative refactors where source-level verification is required, but it establishes the CI/security/doc baseline needed before deeper changes such as entry-point consolidation, `pyproject.toml` migration, and state-path refactoring. + +## Verification + +Expected checks: + +```bash +python -m pip install --upgrade pip +python -m pip install -r requirements.txt +python run_tests.py +python -m compileall . +pylint src run_batllm.py run_game_analyzer.py create_release_bundles.py create_homebrew_formula.py +pip-audit -r requirements.txt +``` + +## Follow-up work + +- Convert runtime configuration writes to use `BATLLM_HOME` everywhere. +- Add migration logic for repository-relative historical config. +- Collapse launchers onto canonical installed entry points. +- Add `pyproject.toml` after confirming package/module names under `src/`. +- Add tests for path handling, missing Ollama, non-responsive Ollama, subprocess timeouts, and session migration. diff --git a/batllm-pr-implementation/PR_TITLE.txt b/batllm-pr-implementation/PR_TITLE.txt new file mode 100644 index 0000000..66765fe --- /dev/null +++ b/batllm-pr-implementation/PR_TITLE.txt @@ -0,0 +1 @@ +Harden CI, dependency security, and runtime state documentation diff --git a/batllm-pr-implementation/SECURITY.md b/batllm-pr-implementation/SECURITY.md new file mode 100644 index 0000000..938dfb6 --- /dev/null +++ b/batllm-pr-implementation/SECURITY.md @@ -0,0 +1,22 @@ +# Security Policy + +## Supported versions + +Security fixes are provided for the current `main` branch and the most recent tagged release. + +## Reporting a vulnerability + +Report suspected vulnerabilities privately. Do not open a public issue containing exploit details, secrets, local paths, or reproduction data that may expose a user system. + +Include: + +- affected BatLLM version or commit; +- operating system and Python version; +- installation method; +- whether Ollama was installed system-wide, through Homebrew, or manually; +- minimal reproduction steps; +- relevant logs with secrets, local usernames, and paths redacted. + +## Security-relevant areas + +BatLLM interacts with a local Ollama service, reads and writes local configuration, stores sessions, and invokes launch scripts. Reports involving path traversal, unsafe subprocess use, unexpected writes outside the configured application directory, dependency compromise, or unintended disclosure of local files should be treated as security relevant. diff --git a/batllm-pr-implementation/docs/MAINTAINER_AUDIT_CHECKLIST.md b/batllm-pr-implementation/docs/MAINTAINER_AUDIT_CHECKLIST.md new file mode 100644 index 0000000..ad9f026 --- /dev/null +++ b/batllm-pr-implementation/docs/MAINTAINER_AUDIT_CHECKLIST.md @@ -0,0 +1,28 @@ +# Maintainer audit checklist + +Use this checklist before release or after changing launch, configuration, packaging, or Ollama lifecycle code. + +## Functional checks + +- `python run_tests.py` passes on Python 3.10, 3.11, and 3.12. +- Application launch works from source checkout. +- Analyzer launch works from source checkout. +- Homebrew launcher and release-bundle launcher call the same canonical application entry path. +- Changing model selection updates only the user state directory. +- Saved sessions are written under the user state directory. +- Legacy session files either migrate deterministically or fail with a clear compatibility message. + +## Security and dependency checks + +- `pip-audit -r requirements.txt` passes or accepted findings are documented. +- Dependency Review passes on pull requests that change dependencies. +- Dependabot pull requests are reviewed and merged or explicitly rejected. +- No launcher uses untrusted shell interpolation. +- Subprocess calls use explicit argument lists, bounded timeouts, and clear error propagation. + +## Platform checks + +- Linux, macOS, and Windows CI pass. +- `BATLLM_HOME` works on all supported platforms. +- Paths with spaces and non-ASCII characters are tested. +- Missing Ollama, stopped Ollama, and non-responsive Ollama produce actionable errors. diff --git a/batllm-pr-implementation/docs/STATE_AND_INSTALLATION.md b/batllm-pr-implementation/docs/STATE_AND_INSTALLATION.md new file mode 100644 index 0000000..d44ae2c --- /dev/null +++ b/batllm-pr-implementation/docs/STATE_AND_INSTALLATION.md @@ -0,0 +1,32 @@ +# Installation channels and mutable state + +BatLLM should use one state model across all installation channels. + +## Invariant + +Installed application files are read-only at runtime. User changes must not mutate the source tree, package installation directory, Homebrew cellar, application bundle, or release-bundle program directory. + +Runtime state belongs in a per-user application directory. `BATLLM_HOME` overrides the default location and is the canonical mechanism for tests, portable bundles, and package-manager integrations. + +## State categories + +| Category | Mutable | Location | +|---|---:|---| +| Packaged defaults | No | repository/package data | +| Effective configuration | Yes | `$BATLLM_HOME/config.yaml` or platform app-data equivalent | +| Saved sessions | Yes | `$BATLLM_HOME/sessions/` | +| Logs | Yes | `$BATLLM_HOME/logs/` | +| Cache/temp files | Yes | `$BATLLM_HOME/cache/` | + +## Required behaviour + +- On first run, create the user state directory if it does not exist. +- Copy packaged default configuration into the user state directory before applying user edits. +- Treat repository-relative `src/configs/config.yaml` as a read-only default, not as runtime state. +- Prefer atomic writes for configuration and saved sessions. +- Do not write to the Homebrew cellar or any other package-manager-controlled directory. +- Tests should set `BATLLM_HOME` to a temporary directory. + +## Migration rule + +If an older install has user-edited configuration in a repository-relative path, migrate it once into the user state directory and leave the original file untouched after migration. diff --git a/batllm-pr-implementation/scripts/apply_audit_pr.sh b/batllm-pr-implementation/scripts/apply_audit_pr.sh new file mode 100755 index 0000000..34d04ad --- /dev/null +++ b/batllm-pr-implementation/scripts/apply_audit_pr.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ ! -d .git ]; then + echo "Run this from the BatLLM repository root." >&2 + exit 1 +fi + +git checkout -b chore/audit-ci-security-state-docs +cp -R .github docs SECURITY.md PR_TITLE.txt PR_BODY.md . +git add . +git commit -m "chore: add audit-driven CI security and state documentation" + +echo "Branch created: chore/audit-ci-security-state-docs" +echo "Open the PR with:" +echo "gh pr create --title \"$(cat PR_TITLE.txt)\" --body-file PR_BODY.md" diff --git a/docs/MAINTAINER_AUDIT_CHECKLIST.md b/docs/MAINTAINER_AUDIT_CHECKLIST.md new file mode 100644 index 0000000..ad9f026 --- /dev/null +++ b/docs/MAINTAINER_AUDIT_CHECKLIST.md @@ -0,0 +1,28 @@ +# Maintainer audit checklist + +Use this checklist before release or after changing launch, configuration, packaging, or Ollama lifecycle code. + +## Functional checks + +- `python run_tests.py` passes on Python 3.10, 3.11, and 3.12. +- Application launch works from source checkout. +- Analyzer launch works from source checkout. +- Homebrew launcher and release-bundle launcher call the same canonical application entry path. +- Changing model selection updates only the user state directory. +- Saved sessions are written under the user state directory. +- Legacy session files either migrate deterministically or fail with a clear compatibility message. + +## Security and dependency checks + +- `pip-audit -r requirements.txt` passes or accepted findings are documented. +- Dependency Review passes on pull requests that change dependencies. +- Dependabot pull requests are reviewed and merged or explicitly rejected. +- No launcher uses untrusted shell interpolation. +- Subprocess calls use explicit argument lists, bounded timeouts, and clear error propagation. + +## Platform checks + +- Linux, macOS, and Windows CI pass. +- `BATLLM_HOME` works on all supported platforms. +- Paths with spaces and non-ASCII characters are tested. +- Missing Ollama, stopped Ollama, and non-responsive Ollama produce actionable errors. diff --git a/docs/SECURITY.md b/docs/SECURITY.md new file mode 100644 index 0000000..1df4e1d --- /dev/null +++ b/docs/SECURITY.md @@ -0,0 +1,8 @@ +# Security Policy + +This project follows responsible disclosure and dependency security best practices. See the root SECURITY.md for the canonical policy. + +- Vulnerabilities should be reported privately to the maintainer. +- Dependency and CI security are enforced via pip-audit, Dependabot, and GitHub Dependency Review. +- No secrets, credentials, or sensitive data should be committed to the repository. +- See [../SECURITY.md](../SECURITY.md) for the full policy and contact details. diff --git a/docs/STATE_AND_INSTALLATION.md b/docs/STATE_AND_INSTALLATION.md new file mode 100644 index 0000000..d44ae2c --- /dev/null +++ b/docs/STATE_AND_INSTALLATION.md @@ -0,0 +1,32 @@ +# Installation channels and mutable state + +BatLLM should use one state model across all installation channels. + +## Invariant + +Installed application files are read-only at runtime. User changes must not mutate the source tree, package installation directory, Homebrew cellar, application bundle, or release-bundle program directory. + +Runtime state belongs in a per-user application directory. `BATLLM_HOME` overrides the default location and is the canonical mechanism for tests, portable bundles, and package-manager integrations. + +## State categories + +| Category | Mutable | Location | +|---|---:|---| +| Packaged defaults | No | repository/package data | +| Effective configuration | Yes | `$BATLLM_HOME/config.yaml` or platform app-data equivalent | +| Saved sessions | Yes | `$BATLLM_HOME/sessions/` | +| Logs | Yes | `$BATLLM_HOME/logs/` | +| Cache/temp files | Yes | `$BATLLM_HOME/cache/` | + +## Required behaviour + +- On first run, create the user state directory if it does not exist. +- Copy packaged default configuration into the user state directory before applying user edits. +- Treat repository-relative `src/configs/config.yaml` as a read-only default, not as runtime state. +- Prefer atomic writes for configuration and saved sessions. +- Do not write to the Homebrew cellar or any other package-manager-controlled directory. +- Tests should set `BATLLM_HOME` to a temporary directory. + +## Migration rule + +If an older install has user-edited configuration in a repository-relative path, migrate it once into the user state directory and leave the original file untouched after migration. diff --git a/packaging/homebrew/requirements.txt b/packaging/homebrew/requirements.txt index c695738..05a2ee3 100644 --- a/packaging/homebrew/requirements.txt +++ b/packaging/homebrew/requirements.txt @@ -1,7 +1,8 @@ +modelito==1.4.0 Kivy==2.3.1 kivymd==1.2.0 Kivy-Garden==0.1.5 -ollama==0.5.3 +ollama>=0.5.11 psutil==7.0.0 PyYAML==6.0.2 -requests==2.32.4 \ No newline at end of file +requests>=2.33.0 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 6b73b63..57a7f91 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ Kivy==2.3.1 kivymd==1.2.0 Kivy-Garden==0.1.5 -ollama==0.5.3 +ollama>=0.5.11 psutil==7.0.0 PyYAML==6.0.2 -requests==2.32.4 -pytest==8.3.5 +requests>=2.33.0 +pytest>=9.0.3 modelito==1.4.0 diff --git a/scripts/apply_audit_pr.sh b/scripts/apply_audit_pr.sh new file mode 100755 index 0000000..34d04ad --- /dev/null +++ b/scripts/apply_audit_pr.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ ! -d .git ]; then + echo "Run this from the BatLLM repository root." >&2 + exit 1 +fi + +git checkout -b chore/audit-ci-security-state-docs +cp -R .github docs SECURITY.md PR_TITLE.txt PR_BODY.md . +git add . +git commit -m "chore: add audit-driven CI security and state documentation" + +echo "Branch created: chore/audit-ci-security-state-docs" +echo "Open the PR with:" +echo "gh pr create --title \"$(cat PR_TITLE.txt)\" --body-file PR_BODY.md"