feat: harden chat state by tenant
This commit is contained in:
@@ -29,6 +29,7 @@ ROOT = project_root()
|
||||
HARNESS_ROOT = os.path.join(ROOT, "packages", "casan-harness")
|
||||
HARNESS_BIN = os.path.join(HARNESS_ROOT, "scripts", "bash")
|
||||
RBAC = os.path.join(HARNESS_BIN, "rbac-check.py")
|
||||
TENANT_STORE = os.path.join(HARNESS_BIN, "tenant-store.sh")
|
||||
GENESIS_HASH = "0" * 64
|
||||
|
||||
|
||||
@@ -44,16 +45,33 @@ 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 registry_path() -> str:
|
||||
return os.environ.get("CASAN_AGENT_REGISTRY_FILE") or os.path.join(HARNESS_ROOT, "config", "agent-registry.yaml")
|
||||
|
||||
|
||||
def audit_path() -> str:
|
||||
return os.environ.get("CASAN_AGENT_BIND_AUDIT_LOG") or os.path.join(state_root(), "logs", "chat", "agent-bindings.jsonl")
|
||||
return guarded_override(os.environ["CASAN_AGENT_BIND_AUDIT_LOG"]) if os.environ.get("CASAN_AGENT_BIND_AUDIT_LOG") else tenant_path("chat/agent-bindings.jsonl", "logs/chat/agent-bindings.jsonl")
|
||||
|
||||
|
||||
def head_path() -> str:
|
||||
return os.environ.get("CASAN_AGENT_BIND_AUDIT_HEAD") or os.path.join(state_root(), "logs", "chat", "agent-bindings-head.txt")
|
||||
return guarded_override(os.environ["CASAN_AGENT_BIND_AUDIT_HEAD"]) if os.environ.get("CASAN_AGENT_BIND_AUDIT_HEAD") else tenant_path("chat/agent-bindings-head.txt", "logs/chat/agent-bindings-head.txt")
|
||||
|
||||
|
||||
def load_registry():
|
||||
@@ -149,6 +167,8 @@ def run_rbac(args):
|
||||
|
||||
|
||||
def bind(args) -> int:
|
||||
if args.tenant and args.tenant != "default":
|
||||
os.environ["CASAN_TENANT_ID"] = args.tenant
|
||||
registry = load_registry()
|
||||
if registry.get("_error"):
|
||||
out = decision_payload(args, "DENIED", registry["_error"])
|
||||
|
||||
Reference in New Issue
Block a user