Per review §2: - web/db.py: new _tx() context manager wraps multi-statement writers in BEGIN IMMEDIATE … COMMIT/ROLLBACK (our connections run in autocommit mode, so plain `with _lock:` doesn't give atomicity). partnership_accept (UPDATE + DELETE) and cleanup_retention (3 deletes/updates) now use it. - Fire-and-forget tasks: add module-level _bg_tasks sets in web/app.py and web/enrichment.py. A _spawn() helper holds a strong ref until the task finishes so the GC can't drop it mid-flight (CPython's event loop only weakly references pending tasks). - apply/main.py: require_api_key uses hmac.compare_digest, matching web's check. Also imports now use explicit names instead of `from settings *`. - apply/language.py: replace `from settings import *` + `from paths import *` with explicit imports — this is the pattern that caused the LANGUAGE NameError earlier. - alert/utils.py: pickle-based hash_any_object → deterministic JSON+sha256. Cheaper, portable across Python versions, no pickle attack surface. - web/notifications.py: /fehler links repointed to /bewerbungen (the former page doesn't exist). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
11 lines
472 B
Python
11 lines
472 B
Python
import hashlib
|
|
import json
|
|
|
|
|
|
def hash_any_object(var) -> str:
|
|
"""Deterministic sha256 over a JSON-encodable value. Replaces the older
|
|
pickle-based hash: pickle is nondeterministic across Python versions /
|
|
dict-ordering tweaks and pulls more attack surface than we need for a
|
|
plain change-detection fingerprint."""
|
|
encoded = json.dumps(var, sort_keys=True, ensure_ascii=False, default=str)
|
|
return hashlib.sha256(encoded.encode("utf-8")).hexdigest()
|