feat: harden chat state by tenant
This commit is contained in:
@@ -33,14 +33,32 @@ def project_root() -> str:
|
||||
ROOT = project_root()
|
||||
BIN = os.path.join(ROOT, "packages", "casan-harness", "scripts", "bash")
|
||||
LOOP_TRACE = os.path.join(BIN, "loop-trace.py")
|
||||
TENANT_STORE = os.path.join(BIN, "tenant-store.sh")
|
||||
|
||||
|
||||
def state_root() -> str:
|
||||
return os.environ.get("CASAN_STATE_ROOT") or os.path.join(ROOT, ".specify")
|
||||
|
||||
|
||||
def tenant_path(logical: str, fallback: str) -> str:
|
||||
if os.environ.get("CASAN_TENANT_ID"):
|
||||
r = subprocess.run(["bash", TENANT_STORE, "resolve", logical], cwd=ROOT, capture_output=True, text=True)
|
||||
if r.returncode != 0:
|
||||
raise SystemExit((r.stderr or r.stdout or "TENANT_DENIED").strip())
|
||||
return r.stdout.strip()
|
||||
return os.path.join(state_root(), fallback)
|
||||
|
||||
|
||||
def guarded_override(path: str) -> str:
|
||||
if path and os.environ.get("CASAN_TENANT_ID"):
|
||||
r = subprocess.run(["bash", TENANT_STORE, "guard", path], cwd=ROOT, capture_output=True, text=True)
|
||||
if r.returncode != 0:
|
||||
raise SystemExit((r.stderr or r.stdout or "TENANT_DENIED").strip())
|
||||
return path
|
||||
|
||||
|
||||
def audit_path() -> str:
|
||||
return os.environ.get("CASAN_CHAT_AUDIT_LOG") or os.path.join(state_root(), "logs", "chat", "chat-turns.jsonl")
|
||||
return guarded_override(os.environ["CASAN_CHAT_AUDIT_LOG"]) if os.environ.get("CASAN_CHAT_AUDIT_LOG") else tenant_path("chat/chat-turns.jsonl", "logs/chat/chat-turns.jsonl")
|
||||
|
||||
|
||||
def sha_text(text: str) -> str:
|
||||
@@ -87,12 +105,12 @@ def resolve_path(path: str) -> str:
|
||||
def loop_state_root(loop_run):
|
||||
explicit = os.environ.get("CASAN_LOOP_STATE_ROOT")
|
||||
if explicit:
|
||||
return explicit
|
||||
return guarded_override(explicit)
|
||||
artifact = loop_run.get("artifact") or ""
|
||||
marker = os.sep + "logs" + os.sep + "chat" + os.sep + "loop-runs" + os.sep
|
||||
if marker in artifact:
|
||||
return artifact.split(marker, 1)[0] + os.sep + "logs" + os.sep + "chat" + os.sep + "loop-state"
|
||||
return os.path.join(state_root(), "logs", "chat", "loop-state")
|
||||
return tenant_path("chat/loop-state", "logs/chat/loop-state")
|
||||
|
||||
|
||||
def run_loop_trace(loop_run, cmd: str):
|
||||
|
||||
Reference in New Issue
Block a user