damage-control-dev 0.1.2__tar.gz → 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/PKG-INFO +1 -1
  2. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/__init__.py +1 -1
  3. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/engine.py +34 -4
  4. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/core.json +15 -0
  5. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/core.yaml +20 -0
  6. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/.gitignore +0 -0
  7. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/LICENSE +0 -0
  8. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/NOTICE +0 -0
  9. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/README.md +0 -0
  10. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/pyproject.toml +0 -0
  11. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/__main__.py +0 -0
  12. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/adapter.py +0 -0
  13. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/audit.py +0 -0
  14. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/breakglass.py +0 -0
  15. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/claude_code.py +0 -0
  16. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/cli.py +0 -0
  17. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/groups.py +0 -0
  18. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/harness_config.py +0 -0
  19. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/hook.py +0 -0
  20. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/install.py +0 -0
  21. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/packs.py +0 -0
  22. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/policy.py +0 -0
  23. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/profile.py +0 -0
  24. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/aws.json +0 -0
  25. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/aws.yaml +0 -0
  26. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/cloud-hosting.json +0 -0
  27. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/cloud-hosting.yaml +0 -0
  28. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/containers.json +0 -0
  29. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/containers.yaml +0 -0
  30. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/control-plane.json +0 -0
  31. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/control-plane.yaml +0 -0
  32. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/databases.json +0 -0
  33. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/databases.yaml +0 -0
  34. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/firebase.json +0 -0
  35. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/firebase.yaml +0 -0
  36. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/gcp.json +0 -0
  37. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/gcp.yaml +0 -0
  38. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/git.json +0 -0
  39. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/git.yaml +0 -0
  40. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/infrastructure.json +0 -0
  41. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/infrastructure.yaml +0 -0
  42. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/mcp-tools.json +0 -0
  43. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/mcp-tools.yaml +0 -0
  44. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/outbound.json +0 -0
  45. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/outbound.yaml +0 -0
  46. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/payloads.json +0 -0
  47. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/payloads.yaml +0 -0
  48. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/publish.json +0 -0
  49. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/publish.yaml +0 -0
  50. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/registry.json +0 -0
  51. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/registry.yaml +0 -0
  52. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/remote.json +0 -0
  53. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/remote.yaml +0 -0
  54. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/tmux.json +0 -0
  55. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/rules/tmux.yaml +0 -0
  56. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/ruleset.py +0 -0
  57. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/aws.json +0 -0
  58. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/aws.yaml +0 -0
  59. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/docker.json +0 -0
  60. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/docker.yaml +0 -0
  61. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/gcp.json +0 -0
  62. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/gcp.yaml +0 -0
  63. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/gh.json +0 -0
  64. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/gh.yaml +0 -0
  65. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/git.json +0 -0
  66. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/git.yaml +0 -0
  67. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/kubectl.json +0 -0
  68. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/kubectl.yaml +0 -0
  69. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/npm.json +0 -0
  70. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/npm.yaml +0 -0
  71. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/terraform.json +0 -0
  72. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/terraform.yaml +0 -0
  73. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/uv.json +0 -0
  74. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/src/damage_control/tooldefs/uv.yaml +0 -0
  75. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/tools/build_rules_json.py +0 -0
  76. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/tools/check_links.py +0 -0
  77. {damage_control_dev-0.1.2 → damage_control_dev-0.1.3}/tools/coverage_matrix.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: damage-control-dev
3
- Version: 0.1.2
3
+ Version: 0.1.3
4
4
  Summary: Damage control for AI coding agents: a PreToolUse guard that blocks or asks before destructive commands and protected-path writes (Claude Code).
5
5
  Project-URL: Homepage, https://github.com/dotdevdotdev/damage-control-dev
6
6
  Project-URL: Source, https://github.com/dotdevdotdev/damage-control-dev
@@ -6,4 +6,4 @@ escape the hook's fail-closed wrapper (a Python crash exits 1, which Claude Code
6
6
  as non-blocking).
7
7
  """
8
8
 
9
- __version__ = "0.1.2"
9
+ __version__ = "0.1.3"
@@ -857,7 +857,11 @@ def _path_context_regex(path: str) -> str:
857
857
  return r'["\']?(?:[^\s"\';|&<>]*/)?' + glob_to_regex(path)
858
858
  expanded = os.path.expanduser(path)
859
859
  if expanded == path:
860
- return re.escape(path)
860
+ if path.startswith("/"):
861
+ return re.escape(path)
862
+ # A bare name (`.git/hooks/`, `node_modules/`, `CLAUDE.md`) is a path
863
+ # component: the same entry guards `/repo/.git/hooks/x` as `.git/hooks/x`.
864
+ return r'["\']?(?:[^\s"\';|&<>]*/)?' + re.escape(path)
861
865
  return r'(?:' + re.escape(expanded) + r'|' + re.escape(path) + r')'
862
866
 
863
867
 
@@ -917,7 +921,18 @@ def path_ladder_haystacks(command: str, path: str) -> List[str]:
917
921
  canon = canonicalize_command(token)
918
922
  return canon != token and bool(keep.search(canon))
919
923
 
920
- return masked_subcommands(mask_sed_substitutions(command), keep=_mentions_path)
924
+ # ``~``/``$HOME``/``${HOME}`` name the home dir and ``{a,b}`` expands before the
925
+ # verb runs: the ladders judge those spellings too, as the zero-access scan does.
926
+ spellings = [command]
927
+ canon = canonicalize_command(command)
928
+ if canon != command:
929
+ spellings.append(canon)
930
+ for text in list(spellings):
931
+ spellings.extend(v for v in brace_variants(text) or () if v not in spellings)
932
+ haystacks: List[str] = []
933
+ for text in spellings:
934
+ haystacks += [h for h in masked_subcommands(mask_sed_substitutions(text), keep=_mentions_path) if h not in haystacks]
935
+ return haystacks
921
936
 
922
937
 
923
938
  def check_path_patterns(
@@ -5975,7 +5990,22 @@ def _guarded_path_test(config: Dict[str, Any]) -> Callable[[str], bool]:
5975
5990
  for p in (config.get(key) or [])
5976
5991
  if isinstance(p, str)
5977
5992
  ]
5978
- return lambda path: is_protected_control_plane(path) or any(match_path(path, p) for p in patterns)
5993
+ # A bare directory entry (`.git/`, `node_modules/`) is a path COMPONENT, not an
5994
+ # absolute prefix: a file inside it is guarded wherever the directory sits, so
5995
+ # `rm hooks/x` run from `<repo>/.git` names a guarded path without saying `.git`.
5996
+ bare_dirs = [
5997
+ "/" + p for p in patterns
5998
+ if p.endswith("/") and not p.startswith(("/", "~")) and not is_glob_pattern(p)
5999
+ ]
6000
+
6001
+ def guarded(path: str) -> bool:
6002
+ if is_protected_control_plane(path) or any(match_path(path, p) for p in patterns):
6003
+ return True
6004
+ fold = str.lower if _casefolds_paths(path) else str
6005
+ probe = fold(path) + "/"
6006
+ return any(fold(d) in probe for d in bare_dirs)
6007
+
6008
+ return guarded
5979
6009
 
5980
6010
 
5981
6011
  def _before_first_cd(command: str) -> str:
@@ -10077,7 +10107,7 @@ def _decide_command(
10077
10107
  # The control plane outranks the escape hatch and the kill switch, so a
10078
10108
  # relative spelling of it is judged before either can end the walk.
10079
10109
  for variant in _cwd_resolved_variants(command, cwd, config):
10080
- inner = _decide_rules(variant, config)
10110
+ inner = _decide_rules(variant, config, cwd)
10081
10111
  if inner.get("protected"):
10082
10112
  return dict(inner, command=command)
10083
10113
  resolved.append(inner)
@@ -191,6 +191,11 @@
191
191
  "~/.pypirc",
192
192
  "~/.git-credentials",
193
193
  ".git-credentials",
194
+ "~/.config/gh/hosts.yml",
195
+ "~/.cargo/credentials.toml",
196
+ "~/.cargo/credentials",
197
+ "~/.gem/credentials",
198
+ "~/.terraform.d/credentials.tfrc.json",
194
199
  "dump.sql",
195
200
  "backup.sql",
196
201
  "*.dump"
@@ -209,6 +214,16 @@
209
214
  "~/.zshrc",
210
215
  "~/.profile",
211
216
  "~/.bash_profile",
217
+ "~/.bash_login",
218
+ "~/.bash_logout",
219
+ "~/.zshenv",
220
+ "~/.zprofile",
221
+ "~/.zlogin",
222
+ "~/.zlogout",
223
+ "~/.gitconfig",
224
+ "~/.config/git/",
225
+ ".git/config",
226
+ ".git/hooks/",
212
227
  "package-lock.json",
213
228
  "yarn.lock",
214
229
  "pnpm-lock.yaml",
@@ -255,6 +255,11 @@ zeroAccessPaths:
255
255
  - "~/.pypirc"
256
256
  - "~/.git-credentials"
257
257
  - ".git-credentials"
258
+ - "~/.config/gh/hosts.yml"
259
+ - "~/.cargo/credentials.toml"
260
+ - "~/.cargo/credentials"
261
+ - "~/.gem/credentials"
262
+ - "~/.terraform.d/credentials.tfrc.json"
258
263
 
259
264
  # ---------------------------------------------------------------------------
260
265
  # DATABASE DUMPS (may contain production data)
@@ -292,6 +297,21 @@ readOnlyPaths:
292
297
  - ~/.zshrc
293
298
  - ~/.profile
294
299
  - ~/.bash_profile
300
+ - ~/.bash_login
301
+ - ~/.bash_logout
302
+ - ~/.zshenv
303
+ - ~/.zprofile
304
+ - ~/.zlogin
305
+ - ~/.zlogout
306
+
307
+ # ---------------------------------------------------------------------------
308
+ # GIT CONFIG AND HOOKS (#1255) - keys such as core.fsmonitor, core.pager and
309
+ # alias.x=!... run programs, and a hook runs on the next git operation
310
+ # ---------------------------------------------------------------------------
311
+ - ~/.gitconfig
312
+ - ~/.config/git/
313
+ - .git/config
314
+ - .git/hooks/
295
315
 
296
316
  # ---------------------------------------------------------------------------
297
317
  # LOCK FILES - Never manually edit, use package managers