plugin.py 1.1 KB

12345678910111213141516171819202122232425262728293031323334
  1. """The plugin's fixed names, and its own manifest."""
  2. from __future__ import annotations
  3. import re
  4. from pathlib import Path
  5. from . import strictjson
  6. from .strictjson import is_map, is_str
  7. NAME = "claude-security"
  8. ROOT = Path(__file__).resolve().parents[2]
  9. RUN_DIR_NAME = ".claude-security-run"
  10. TARGET_FILES_NAME = "target-files.json"
  11. # Set only by workflows/scan.js (its PROVENANCE) on each vote record it computes.
  12. VOTES_PROVENANCE = "workflows/scan.js"
  13. MODES = ("scan", "changes", "commit")
  14. REPORT_DIR_PREFIX = "CLAUDE-SECURITY-"
  15. # \Z, not $: `$` also matches before a trailing newline, and this id names product files.
  16. SHA_RE = re.compile(r"^[0-9a-fA-F]{7,64}\Z")
  17. def version() -> str | None:
  18. """The non-blank version string in the plugin's manifest, or None when there is not one."""
  19. try:
  20. manifest = strictjson.load(ROOT / ".claude-plugin" / "plugin.json")
  21. except (OSError, ValueError):
  22. return None
  23. if not is_map(manifest):
  24. return None
  25. declared = manifest.get("version")
  26. if not is_str(declared):
  27. return None
  28. return declared.strip() or None