"""Identity editor and current assistant name, authenticated by Alfred's admin UI. Identity is stored natively in Hermes SOUL.md, not injected into questions. All writes are atomic; dated revisions are kept separately. Technical names/paths/API identifiers are never renamed. """ from __future__ import annotations import hashlib import json import os from pathlib import Path import re import tempfile import threading from datetime import datetime from flask import Blueprint, jsonify, render_template, request from services import admin_console ROOT = Path(__file__).resolve().parents[1] CONFIG = ROOT / 'config' IDENTITY = Path('/root/.hermes/SOUL.md') TRACKER = CONFIG / 'identity_name_state.json' HISTORY = CONFIG / 'identity_history' LOCK = threading.RLock() MAX_SIZE = 40_000 ASSISTANT_RE = re.compile(r"(? MAX_SIZE or '\x00' in text: return jsonify(error='L’identité doit être non vide et ne pas dépasser 40 Ko.'), 400 if not re.fullmatch(r'[0-9a-f]{64}', revision): return jsonify(error='Révision invalide.'), 400 try: with LOCK: path = identity_path() old = _read_text() if sha(old) != revision: return jsonify(error='Le fichier a changé depuis ton chargement. Recharge avant d’enregistrer.'), 409 if text != old: _revision(old, 'avant_edition') mode = (path.stat().st_mode & 0o777) if path.exists() else 0o600 _save_atomic(path, text, mode) res = jsonify(ok=True, revision=sha(text), name=active_name(), updated=text != old, file='/root/.hermes/SOUL.md') res.headers['Cache-Control'] = 'no-store, private' return res except (OSError, ValueError) as e: return jsonify(error='Enregistrement impossible : '+str(e)), 500 app.register_blueprint(bp) # No startup rewrite: keep manually edited SOUL.md intact.