feat: harden control panel authentication

This commit is contained in:
thanhnv
2026-07-10 23:48:12 +09:00
parent 48b1186439
commit b56f7d357e
11 changed files with 571 additions and 73 deletions
@@ -204,29 +204,36 @@ def call_account_model(provider: str, prompt: str):
def audit(job: dict, status: str) -> str:
path = os.path.join(STATE_ROOT, "logs", "audit", "goal-orchestrator.jsonl")
head_path = os.path.join(STATE_ROOT, "logs", "audit", "goal-orchestrator-head.txt")
lock_path = os.path.join(STATE_ROOT, "logs", "audit", "goal-orchestrator.lock")
os.makedirs(os.path.dirname(path), exist_ok=True)
previous = "0" * 64
try:
with open(head_path, encoding="utf-8") as handle:
previous = handle.read().strip() or previous
except OSError:
pass
core = {
"timestamp": now(),
"harness": "H5-governance",
"goal_id": job["id"],
"tenant": job.get("tenant", "default"),
"actor": job.get("actor", "unknown"),
"goal_hash": sha(str(job.get("goal", ""))),
"status": status,
"local_provider": job.get("local_provider", ""),
"cloud_provider": job.get("cloud_provider", ""),
"prev_hash": previous,
}
record_hash = sha(json.dumps(core, sort_keys=True, ensure_ascii=False))
append_jsonl(path, {**core, "record_hash": record_hash})
with open(head_path, "w", encoding="utf-8") as handle:
handle.write(record_hash + "\n")
with open(lock_path, "a", encoding="utf-8") as lock:
fcntl.flock(lock.fileno(), fcntl.LOCK_EX)
previous = "0" * 64
try:
with open(head_path, encoding="utf-8") as handle:
previous = handle.read().strip() or previous
except OSError:
pass
core = {
"timestamp": now(),
"harness": "H5-governance",
"goal_id": job["id"],
"tenant": job.get("tenant", "default"),
"actor": job.get("actor", "unknown"),
"goal_hash": sha(str(job.get("goal", ""))),
"status": status,
"local_provider": job.get("local_provider", ""),
"cloud_provider": job.get("cloud_provider", ""),
"prev_hash": previous,
}
record_hash = sha(json.dumps(core, sort_keys=True, ensure_ascii=False))
append_jsonl(path, {**core, "record_hash": record_hash})
with open(head_path, "w", encoding="utf-8") as handle:
handle.write(record_hash + "\n")
handle.flush()
os.fsync(handle.fileno())
os.chmod(head_path, 0o600)
fcntl.flock(lock.fileno(), fcntl.LOCK_UN)
return record_hash
@@ -351,10 +358,43 @@ def run(job_path: str) -> int:
return 2
def verify_audit() -> int:
path = os.path.join(STATE_ROOT, "logs", "audit", "goal-orchestrator.jsonl")
previous = "0" * 64
records = 0
try:
handle = open(path, encoding="utf-8")
except OSError:
print(json.dumps({"ok": True, "records": 0, "head": previous}))
return 0
with handle:
for line in handle:
if not line.strip():
continue
records += 1
try:
record = json.loads(line)
except ValueError:
print(json.dumps({"ok": False, "records": records, "reason": "invalid_json"}))
return 3
record_hash = str(record.pop("record_hash", ""))
expected = sha(json.dumps(record, sort_keys=True, ensure_ascii=False))
if record.get("prev_hash") != previous or record_hash != expected:
print(json.dumps({"ok": False, "records": records, "reason": "chain_break"}))
return 3
previous = record_hash
print(json.dumps({"ok": True, "records": records, "head": previous}))
return 0
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--job-file", required=True)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--job-file")
group.add_argument("--verify-audit", action="store_true")
args = parser.parse_args()
if args.verify_audit:
return verify_audit()
path = os.path.abspath(args.job_file)
state = os.path.abspath(STATE_ROOT) + os.sep
if not path.startswith(state):