Pre-publish privacy audit: scrub the simulator serial, harden the sdist, add licences
Audited the package against the two-stage procedure before a first PyPI publish. The sdist and wheel were already tight, but three things needed fixing and the controls needed to become real rather than documented. The simulator volunteered high="PI04" as its product serial, which is the real Bebop 2 serial prefix. Nothing unique to one aircraft, but a realistic prefix invites being quoted into a bug report as a specimen, so it now reads "N0TAREAL" / "0000000SIM" with a comment saying why it is nonsense on purpose. The low half and the 500.0 no-fix GPS sentinel were already fake. Hardened [tool.uv.build-backend] source-exclude well past the directories that exist today: captures at any depth, log dumps, recorded media by extension, caches, and anything credential-shaped. .gitignore governs git and source-exclude governs the sdist; a capture can sit in one and not the other, which is how this kind of data reaches an immutable index. Verified the broad patterns do not over-reach: arsdk-xml/ with PROVENANCE.md and tools/logs.py both still ship. Added LICENSE (MIT) and LICENSE-arsdk-xml (Parrot SA's BSD-3-Clause), and corrected the declared licence to "MIT AND BSD-3-Clause". The vendored XML ships in both artifacts because nothing here decodes a command without it, so MIT alone understated what is in the box. Both texts now appear in the artifacts and in the metadata. test_packaging.py grows privacy guards that fail on a serial prefix, a P7 CPU id, any MAC, a high-precision coordinate, an absolute home path, or any private address other than the drone's own documented 192.168.42.0/24. Each pattern was checked against the real identifiers to confirm it bites, since a guard that passes on an empty tree proves nothing. Example address in test_arsdk_session.py moved to RFC 5737 space. 504 tests pass, ruff clean.
This commit is contained in:
+77
-2
@@ -4,7 +4,11 @@ version = "2026.10.02"
|
||||
description = "MCP server for the Parrot Bebop 2 drone: telemetry, camera, files, and every ARSDK command"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
license = "MIT"
|
||||
# Our own code is MIT. The vendored arsdk-xml/ is Parrot SA's, BSD-3-Clause,
|
||||
# and it ships in both artifacts because the package cannot decode a single
|
||||
# command without it, so the distribution as a whole is both.
|
||||
license = "MIT AND BSD-3-Clause"
|
||||
license-files = ["LICENSE", "LICENSE-arsdk-xml"]
|
||||
authors = [{name = "Ryan Malloy", email = "ryan@supported.systems"}]
|
||||
keywords = ["mcp", "drone", "parrot", "bebop", "arsdk", "fastmcp"]
|
||||
classifiers = [
|
||||
@@ -35,7 +39,78 @@ requires = ["uv_build>=0.11.3,<0.12.0"]
|
||||
build-backend = "uv_build"
|
||||
|
||||
[tool.uv.build-backend]
|
||||
source-exclude = ["CLAUDE.md", ".env", ".env.*", ".mcp.json", "tests", "captures"]
|
||||
# Err toward excluding. This repo sits next to a real aircraft, and `captures/`
|
||||
# holds video of the owner's home plus `ckcm.bin` system logs that carry the
|
||||
# serial, the CPU id and a real GPS fix together. None of it may ever reach an
|
||||
# sdist, which is immutable and mirrored within minutes of upload.
|
||||
#
|
||||
# `.gitignore` does NOT protect this: it governs git, and source-exclude
|
||||
# governs the sdist. A file can easily be in one and not the other, so the
|
||||
# patterns below are deliberately broader than the directories that exist
|
||||
# today -- a capture dropped into a new directory next year is still excluded.
|
||||
# test_packaging.py asserts both halves stay in agreement.
|
||||
source-exclude = [
|
||||
# Operator-private context and anything credential-shaped.
|
||||
"CLAUDE.md",
|
||||
".env",
|
||||
".env.*",
|
||||
".mcp.json",
|
||||
".claude",
|
||||
".claude/**",
|
||||
# Dev-only trees. Tests carry fixtures copy-pasted from a live aircraft.
|
||||
"tests",
|
||||
"tests/**",
|
||||
"docs",
|
||||
"docs/**",
|
||||
"scripts",
|
||||
"scripts/**",
|
||||
"*.ipynb",
|
||||
# Captures off the aircraft, at any depth, plus log dumps.
|
||||
"captures",
|
||||
"captures/**",
|
||||
"**/captures/**",
|
||||
"**/logs/**",
|
||||
"ckcm*",
|
||||
"**/ckcm*",
|
||||
# Recorded media and binary blobs by extension, so a stray file in a
|
||||
# directory nobody thought to list is still caught.
|
||||
"*.rtpcap",
|
||||
"*.raw",
|
||||
"*.h264",
|
||||
"*.bin",
|
||||
"*.pcap",
|
||||
"*.pcapng",
|
||||
"*.mp4",
|
||||
"*.jpg",
|
||||
"*.jpeg",
|
||||
"*.png",
|
||||
"*.wav",
|
||||
"*.ulg",
|
||||
"**/*.rtpcap",
|
||||
"**/*.raw",
|
||||
"**/*.h264",
|
||||
"**/*.bin",
|
||||
"**/*.jpg",
|
||||
"**/*.jpeg",
|
||||
"**/*.png",
|
||||
# Caches and build output. .pyc files embed the absolute build path, which
|
||||
# leaks a username and the local directory layout.
|
||||
"**/__pycache__",
|
||||
"**/__pycache__/**",
|
||||
"*.pyc",
|
||||
"**/*.pyc",
|
||||
".pytest_cache",
|
||||
".pytest_cache/**",
|
||||
".ruff_cache",
|
||||
".ruff_cache/**",
|
||||
".venv",
|
||||
".venv/**",
|
||||
"dist",
|
||||
"dist/**",
|
||||
"build",
|
||||
"build/**",
|
||||
"*.egg-info",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
dev = ["ruff>=0.16", "pytest>=8.0", "pytest-asyncio>=0.25"]
|
||||
|
||||
Reference in New Issue
Block a user