From 210d8382312279be86cc34d5cf2744a2f59e27f3 Mon Sep 17 00:00:00 2001 From: sh4un Date: Tue, 25 Aug 2026 18:17:38 -0400 Subject: [PATCH] Keep secrets and personal workspaces out of git Harden .gitignore for live config, credentials, keys, logs, editor workspaces, and local agent directories. Stop tracking personal VS Code settings and add a regression test for the ignore rules. --- .gitignore | 107 +++++++++++++++++++++++++++++-- .vscode/settings.json | 4 -- CHANGELOG.md | 1 + MANIFEST.in | 5 +- docs/configuration.md | 4 +- examples/config.local.mqtt.ini | 1 + examples/config.local.serial.ini | 1 + tests/test_gitignore.py | 78 ++++++++++++++++++++++ 8 files changed, 188 insertions(+), 13 deletions(-) delete mode 100644 .vscode/settings.json create mode 100644 tests/test_gitignore.py diff --git a/.gitignore b/.gitignore index 672b7e0..4dae9d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,111 @@ # .gitignore +# Keep operator secrets, keys, logs, and local tooling out of git. +# --- Secrets and operator config --- +# Live config can contain MQTT passwords, API tokens, and TLS paths. +config.ini +*.local.ini +*.local.*.ini +!examples/config.local.mqtt.ini +!examples/config.local.serial.ini +tmp_*.ini +secrets.ini +secrets.* +credentials.* +*.secret + +# Environment files +.env +.env.* +!.env.example + +# Private keys, certificates, and trust stores +*.pem +*.key +*.p12 +*.pfx +*.crt +*.cer +*.der +*.keystore +*.jks +id_rsa +id_rsa.pub +id_dsa +id_dsa.pub +id_ecdsa +id_ecdsa.pub +id_ed25519 +id_ed25519.pub + +# --- Runtime logs (may contain message payloads) --- +*.log +logs/ +*.jsonl +*.jsonl.[0-9]* +ammb_tui_crash.log + +# --- Python --- __pycache__/ *.py[cod] +*$py.class +*.so +.Python .venv/ venv/ env/ -config.ini -.pytest_cache/ -.coverage -htmlcov/ -*.log +ENV/ +env.bak/ +venv.bak/ +*.egg-info/ +*.egg +.eggs/ dist/ build/ -akita_mesh_bridge.egg-info/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +.installed.cfg tmp_*.py -tmp_*.ini + +# --- Test / type / coverage caches --- +.pytest_cache/ .mypy_cache/ +.ruff_cache/ +.tox/ +.nox/ +.coverage +.coverage.* +coverage.xml +htmlcov/ +.hypothesis/ +.cache +.dmypy.json +dmypy.json + +# --- Personal editors, workspaces, and local agent dirs --- +.vscode/ +.idea/ +.vs/ +*.code-workspace +*.sublime-workspace +*.sublime-project +*.user +.cursor/ +.claude/ +.codex/ +.grok/ +.windsurf/ +.continue/ +.direnv/ +.envrc +!.envrc.example +/personal/ +/workspace/ +/workspaces/ +*.swp +*.swo +*~ +.DS_Store +Thumbs.db +Desktop.ini diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 4b5a294..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "python-envs.defaultEnvManager": "ms-python.python:conda", - "python-envs.defaultPackageManager": "ms-python.python:conda" -} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 273024f..8413b6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ ## Unreleased ### Maintenance +- **Hardened** `.gitignore` so live `config.ini`, `.env` files, TLS keys, message logs, crash dumps, editor workspaces, and personal local directories cannot be committed. Example configs under `examples/` remain tracked. - **Added** `.flake8` configuration to exclude `.venv` from linting to avoid third-party noise in CI and local runs. - **Documented** project linting policy (79-char E501 limit, prefer wrapping and parameterized logging, and do not edit third-party site-packages). - **Fixed** project E501 and other flake8 issues in `ammb/` and `examples/`; tests and `mypy` were run and verified clean. diff --git a/MANIFEST.in b/MANIFEST.in index 0e77961..d1c5db0 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,8 @@ include CHANGELOG.md include DEPLOYMENT.md recursive-include docs *.md -recursive-include examples *.ini *.example +include examples/config.ini.example +include examples/config.local.mqtt.ini +include examples/config.local.serial.ini +include examples/meshcore_simulator.py recursive-include packaging *.service diff --git a/docs/configuration.md b/docs/configuration.md index c5df206..cef890d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -314,9 +314,11 @@ For different environments (development, production), you can: ## Security Considerations +- **Do not commit live config:** `config.ini` is gitignored because it can contain `MQTT_PASSWORD`, `API_TOKEN`, and TLS certificate paths. Copy `examples/config.ini.example` (or the MQTT/serial local examples) and keep secrets out of git. - **MQTT Passwords**: Store securely, consider using environment variables for sensitive data -- **TLS Certificates**: Use proper certificate paths and avoid insecure mode in production +- **TLS Certificates**: Use proper certificate paths and avoid insecure mode in production. Certificate and key files (`*.pem`, `*.key`, `*.crt`) are gitignored. - **API Access**: Restrict API host to localhost (127.0.0.1), set `API_TOKEN`, and use a reverse proxy if remote access is required +- **Message logs**: `MESSAGE_LOG_FILE` JSONL output and `ammb_tui_crash.log` are gitignored so payloads are not uploaded. - **Serial Ports**: Ensure proper permissions are set on serial devices ## Troubleshooting Configuration diff --git a/examples/config.local.mqtt.ini b/examples/config.local.mqtt.ini index 49d5461..d5fadd0 100644 --- a/examples/config.local.mqtt.ini +++ b/examples/config.local.mqtt.ini @@ -1,5 +1,6 @@ ; examples/config.local.mqtt.ini ; Local config for testing the bridge with a local MQTT broker (recommended) +; Public template only. Do not put production passwords or API tokens here. [DEFAULT] MESHTASTIC_SERIAL_PORT = /dev/ttyUSB0 diff --git a/examples/config.local.serial.ini b/examples/config.local.serial.ini index 96ad56a..4251cbe 100644 --- a/examples/config.local.serial.ini +++ b/examples/config.local.serial.ini @@ -1,5 +1,6 @@ ; examples/config.local.serial.ini ; Local config for testing the bridge with a serial simulator (Windows example) +; Public template only. Do not put production passwords or API tokens here. [DEFAULT] MESHTASTIC_SERIAL_PORT = COM5 ; simulator writes here diff --git a/tests/test_gitignore.py b/tests/test_gitignore.py new file mode 100644 index 0000000..2103b5b --- /dev/null +++ b/tests/test_gitignore.py @@ -0,0 +1,78 @@ +"""Guard that operator secrets cannot be committed.""" + +import subprocess +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] + +# Paths that may contain credentials, keys, or message payloads. +MUST_IGNORE = ( + "config.ini", + "config.local.ini", + "config.local.mqtt.ini", + "secrets.ini", + "credentials.json", + ".env", + ".env.local", + "mqtt.pem", + "mqtt.key", + "client.crt", + "id_rsa", + "ammb_tui_crash.log", + "messages.jsonl", + "messages.jsonl.1", + "coverage.xml", + ".vscode/settings.json", + ".vscode/launch.json", + ".idea/workspace.xml", + "project.code-workspace", + ".cursor/", + ".claude/", + ".grok/", + "personal/notes.txt", + "workspace/local.ini", +) + +# Public templates that must remain shareable. +MUST_NOT_IGNORE = ( + "examples/config.ini.example", + "examples/config.local.mqtt.ini", + "examples/config.local.serial.ini", +) + + +def _check_ignore(path: str) -> int: + result = subprocess.run( + ["git", "check-ignore", "--no-index", "-q", path], + cwd=ROOT, + check=False, + ) + return result.returncode + + +def test_secret_paths_are_gitignored(): + for path in MUST_IGNORE: + assert _check_ignore(path) == 0, f"{path} must be gitignored" + + +def test_example_configs_remain_tracked(): + for path in MUST_NOT_IGNORE: + assert _check_ignore(path) == 1, f"{path} must not be gitignored" + + +def test_gitignore_covers_required_patterns(): + text = (ROOT / ".gitignore").read_text(encoding="utf-8") + for pattern in ( + "config.ini", + ".env", + "*.pem", + "*.key", + "*.jsonl", + "ammb_tui_crash.log", + ".vscode/", + "*.code-workspace", + "/personal/", + "/workspace/", + ): + assert pattern in text