key-amnesia 0.3.2__py3-none-any.whl
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.
- key_amnesia/__init__.py +8 -0
- key_amnesia/__main__.py +4 -0
- key_amnesia/audit.py +55 -0
- key_amnesia/cli.py +753 -0
- key_amnesia/clipboard.py +9 -0
- key_amnesia/config.py +74 -0
- key_amnesia/crypto.py +57 -0
- key_amnesia/guard.py +695 -0
- key_amnesia/hooks/__init__.py +1 -0
- key_amnesia/hooks/secret_guard.py +260 -0
- key_amnesia/ipc.py +66 -0
- key_amnesia/paths.py +62 -0
- key_amnesia/platform.py +265 -0
- key_amnesia/prompt_route.py +652 -0
- key_amnesia/run_exec.py +55 -0
- key_amnesia/scrub.py +25 -0
- key_amnesia/setup_cmd.py +179 -0
- key_amnesia/skills/key-amnesia-hygiene/SKILL.md +55 -0
- key_amnesia/skills/key-amnesia-migrate/SKILL.md +72 -0
- key_amnesia/skills/key-amnesia-usage/SKILL.md +66 -0
- key_amnesia/theme.py +290 -0
- key_amnesia/vault.py +168 -0
- key_amnesia-0.3.2.dist-info/METADATA +177 -0
- key_amnesia-0.3.2.dist-info/RECORD +28 -0
- key_amnesia-0.3.2.dist-info/WHEEL +5 -0
- key_amnesia-0.3.2.dist-info/entry_points.txt +4 -0
- key_amnesia-0.3.2.dist-info/licenses/LICENSE +201 -0
- key_amnesia-0.3.2.dist-info/top_level.txt +1 -0
key_amnesia/__init__.py
ADDED
key_amnesia/__main__.py
ADDED
key_amnesia/audit.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""JSONL audit log — never records secret values."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, Iterable
|
|
9
|
+
|
|
10
|
+
from key_amnesia.paths import audit_log_path
|
|
11
|
+
|
|
12
|
+
VALID_ROUTES = frozenset({"inline", "spawned-console", "guard-session"})
|
|
13
|
+
VALID_RESULTS = frozenset({"allowed", "denied", "timeout"})
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _utc_now_iso() -> str:
|
|
17
|
+
return datetime.now(timezone.utc).replace(microsecond=0).isoformat()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def audit_event(
|
|
21
|
+
action: str,
|
|
22
|
+
*,
|
|
23
|
+
secret_names: Iterable[str] | None = None,
|
|
24
|
+
command: list[str] | str | None = None,
|
|
25
|
+
route: str,
|
|
26
|
+
result: str,
|
|
27
|
+
reason: str = "",
|
|
28
|
+
path: Path | None = None,
|
|
29
|
+
) -> dict[str, Any]:
|
|
30
|
+
"""Append one audit record. Never includes secret values or passwords."""
|
|
31
|
+
if route not in VALID_ROUTES:
|
|
32
|
+
raise ValueError(f"Invalid audit route: {route}")
|
|
33
|
+
if result not in VALID_RESULTS:
|
|
34
|
+
raise ValueError(f"Invalid audit result: {result}")
|
|
35
|
+
|
|
36
|
+
if isinstance(command, list):
|
|
37
|
+
cmd_field: str | list[str] | None = list(command)
|
|
38
|
+
else:
|
|
39
|
+
cmd_field = command
|
|
40
|
+
|
|
41
|
+
record: dict[str, Any] = {
|
|
42
|
+
"timestamp": _utc_now_iso(),
|
|
43
|
+
"action": action,
|
|
44
|
+
"secret_names": list(secret_names or []),
|
|
45
|
+
"command": cmd_field,
|
|
46
|
+
"route": route,
|
|
47
|
+
"result": result,
|
|
48
|
+
"reason": reason,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
p = path or audit_log_path()
|
|
52
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
53
|
+
with p.open("a", encoding="utf-8") as f:
|
|
54
|
+
f.write(json.dumps(record, separators=(",", ":")) + "\n")
|
|
55
|
+
return record
|