fix(profiles): sweep the remaining pre-write mkdirs under the deleted-profile guard
A long-lived serve process keeps a deleted profile as the context home of threads that outlive the delete. A bare `mkdir(parents=True)` right before an atomic write brings `profiles/<name>/` back after `hermes profile delete` has written the tombstone and removed the tree. The writers in `utils` and the seven callers named in #112592 are guarded by the preceding commits; this one applies the same `mkdir_under_hermes_home` idiom to the other pre-write directory creations found by the same mechanical rule (auth, personality, plugin catalog, skills sync, tool discovery cache, platform adapters, memory plugins, local runtime supervisor, process identity, breadcrumbs). The two sites that pass `mode=` keep their mkdir behind `assert_named_profile_home_live`. The guard is a no-op unless the target has a provable `profiles/<name>` ancestor. Salvaged from #112596 (30-file sweep) on top of #112594 / #112601; the overlapping files were resolved to the already-landed versions.
This commit is contained in:
@@ -149,7 +149,8 @@ def _write_config(cfg: dict, path: Path | None = None) -> None:
|
||||
out = _apply_edits(cfg.snapshot, cfg, disk)
|
||||
elif path.exists():
|
||||
out = _apply_edits(cfg.snapshot, cfg, _overlay_local(cfg.snapshot, disk))
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
from hermes_constants import mkdir_under_hermes_home
|
||||
mkdir_under_hermes_home(path.parent)
|
||||
atomic_json_write(path, out, mode=0o600)
|
||||
if isinstance(cfg, _ReadConfig): # a later write on the same object applies only edits made after this one
|
||||
cfg.snapshot, cfg.path = copy.deepcopy(dict(cfg)), path
|
||||
|
||||
@@ -2216,7 +2216,8 @@ class OpenVikingMemoryProvider(MemoryProvider):
|
||||
logger.debug("Could not safely mark OpenViking session %s pending without a run lock", sid)
|
||||
return
|
||||
try:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
from hermes_constants import mkdir_under_hermes_home
|
||||
mkdir_under_hermes_home(path.parent)
|
||||
atomic_json_write(path, {"session_id": sid, "owner_run_id": self._run_id}, mode=0o600)
|
||||
self._pending_marked_sids.add(sid)
|
||||
except Exception as e:
|
||||
|
||||
@@ -321,7 +321,8 @@ def _mirror_manual_config_to_openviking_store(*, prompt, select, cancelled, valu
|
||||
return _SETUP_CANCELLED
|
||||
if replace is False:
|
||||
continue
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
from hermes_constants import mkdir_under_hermes_home
|
||||
mkdir_under_hermes_home(path.parent)
|
||||
# atomic_json_write creates the temp file 0600 and os.replace()s it: no
|
||||
# half-written config on crash, no chmod-after-write window for the keys.
|
||||
ov.atomic_json_write(path, ov._ovcli_data_from_connection_values(values), mode=0o600)
|
||||
|
||||
@@ -3449,7 +3449,8 @@ class FeishuAdapter(BasePlatformAdapter):
|
||||
|
||||
def _persist_seen_message_ids(self) -> None:
|
||||
try:
|
||||
self._dedup_state_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
from hermes_constants import mkdir_under_hermes_home
|
||||
mkdir_under_hermes_home(self._dedup_state_path.parent)
|
||||
with self._dedup_lock:
|
||||
recent = self._seen_message_order[-self._dedup_cache_size:]
|
||||
# Save as {msg_id: timestamp} so TTL filtering works across restarts.
|
||||
|
||||
@@ -195,7 +195,8 @@ def _chmod_quiet(path: Path, mode: int) -> None:
|
||||
|
||||
def _write_private_json(path: Path, data: Any) -> None:
|
||||
"""Atomically write JSON with 0o600 permissions (0o700 parent) where supported."""
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
from hermes_constants import mkdir_under_hermes_home
|
||||
mkdir_under_hermes_home(path.parent)
|
||||
_chmod_quiet(path.parent, 0o700)
|
||||
# mkstemp's 0o600 temp + atomic rename never exposes the token at process umask.
|
||||
atomic_write_text(path, json.dumps(data, indent=2, ensure_ascii=False), create_mode=0o600)
|
||||
|
||||
Reference in New Issue
Block a user