The Agents views gain a Hierarchie view: an org chart of the chair and the line offices read from the council claims. The operator appoints, hands over and recalls an office there; the page signs each change with the passkey and a host unit (client/offices.py, offices path unit) verifies the signature, removes a live holder itself and runs a plain council.py claim for the successor. council.py loses the --operator flag, so no agent can override a live holder. The agent order is now separate from task priority: rasci.py agents order stores it in agent-order.json beside the register through the nofollow helpers and never writes a --prio pin. It only breaks ties of equal task rank, also among the queue grants. The Hierarchie view edits it as a drag list. Host units run the installed skill scripts, so orchestrator.sh keeps the offices unit off while the installed council.py, nofollow.py or rasci.py differ from the tree. Job files, council files and hub records are read with O_NOFOLLOW and O_NONBLOCK and size caps; nofollow.rewrite replaces a claim without creating directories, so a beat never revives a released office. 🎯 Fix: 92 % 💥 Break: 4 % 💸 Cost: 100 % ⏱️ Time: 79 % 🛡️ Security: 100 % 🏆 Score: 100 🚦 Gate: ✅ 90/5, cost and time <= 100, security 100 % Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
325 lines
21 KiB
Python
325 lines
21 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import json
|
|
import os
|
|
import re
|
|
import secrets
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import time
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest import mock
|
|
|
|
from hub_case import HubCase
|
|
from hub_support import HUB, ORIGIN, REPO_ROOT, key, signing, verifier
|
|
|
|
OFFICES = HUB / "client" / "offices.py"
|
|
OFFICES_SPEC = importlib.util.spec_from_file_location("kvb_orchestrator_offices_runner", OFFICES)
|
|
host = importlib.util.module_from_spec(OFFICES_SPEC)
|
|
OFFICES_SPEC.loader.exec_module(host)
|
|
COUNCIL_SCRIPT = REPO_ROOT / "skills" / "kvb-org-organize" / "scripts" / "council.py"
|
|
SINCE = "2026-11-07T08:00:00+00:00"
|
|
|
|
|
|
def office_claim(office: str, session: str, name: str, runtime: str) -> dict:
|
|
return {"office": office, "session": session, "runtime": runtime, "name": name, "since": SINCE, "beat": time.time(), "work": f"{office} work"}
|
|
|
|
|
|
def unblock(fifo: Path) -> None:
|
|
try:
|
|
os.close(os.open(fifo, os.O_WRONLY | os.O_NONBLOCK))
|
|
except OSError:
|
|
pass
|
|
|
|
|
|
class TestHubOffices(HubCase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.write_council({
|
|
"chair/claim.json": office_claim("chair", "s1", "Maintainer", "claude-code"),
|
|
"identity/oidc/claim.json": office_claim("identity/oidc", "s2", "Skills", "claude-code"),
|
|
"work/hub/claim.json": office_claim("work/hub", "s3", "Stage", "claude-code"),
|
|
"cluster/gate/claim.json": office_claim("cluster/gate", "s2", "Skills", "claude-code"),
|
|
})
|
|
self.snapshot()
|
|
|
|
def sign(self, items: list[dict]) -> tuple[int, bytes]:
|
|
status, _, body = self.post_json("/api/sign", {"items": items}, self.guard(self.host))
|
|
return status, body
|
|
|
|
def test_the_chair_is_the_holder_of_the_chair_office(self):
|
|
state = self.snapshot()
|
|
self.assertEqual([(node["id"], node["kind"]) for node in state["graph"]["nodes"][:2]], [("Operator", "operator"), ("s1", "chair")])
|
|
self.assertEqual({claim["office"]: claim["kind"] for claim in state["claims"]}, {"chair": "chair", "cluster/gate": "cluster", "identity/oidc": "line", "work/hub": "work"})
|
|
code = re.sub(r'<script nonce="[^"]+" id="state" type="application/json">.*?</script>', "", self.index(), flags=re.DOTALL)
|
|
self.assertNotIn("Maintainer", code)
|
|
|
|
def test_a_fifo_or_link_at_a_council_file_never_blocks_or_feeds_the_state(self):
|
|
fifos = [self.council / "work" / "fifo" / "claim.json", self.council / "agent-order.json"]
|
|
fifos[0].parent.mkdir(parents=True)
|
|
for fifo in fifos:
|
|
os.mkfifo(fifo, 0o600)
|
|
self.addCleanup(unblock, fifo)
|
|
planted = self.outside / "claim.json"
|
|
planted.write_text(json.dumps(office_claim("security/gui", "s9", "Linked", "claude-code")), encoding="utf-8")
|
|
(self.council / "security" / "gui").mkdir(parents=True)
|
|
(self.council / "security" / "gui" / "claim.json").symlink_to(planted)
|
|
offices = [claim["office"] for claim in self.snapshot()["claims"]]
|
|
self.assertEqual(offices, ["chair", "cluster/gate", "identity/oidc", "work/hub"])
|
|
|
|
def test_a_vacant_chair_draws_no_chair_node_and_the_operator_grants(self):
|
|
shutil.rmtree(self.council / "chair")
|
|
now = time.time()
|
|
self.write_council({
|
|
"rasci.json": {"work/hub": {"title": "Hub", "status": "running", "worker": "Stage", "workdir": "/repo/hub", "roles": {"Stage": "RA"}}},
|
|
"queue-history.jsonl": self.jsonl([{"id": "q1", "kind": "gate", "workdir": "/repo/hub", "start": now - 10, "end": now - 5, "exit": 0}]),
|
|
})
|
|
state = self.snapshot()
|
|
self.assertEqual([node["kind"] for node in state["graph"]["nodes"]].count("chair"), 0)
|
|
self.assertIn({"source": "Operator", "target": "s3", "class": "grant", "count": 1}, state["graph"]["edges"])
|
|
|
|
def test_signing_an_office_needs_a_known_session_the_current_holder_and_one_line_per_dimension(self):
|
|
for name, item in (
|
|
("appoint a vacant line", signing.office_item("appoint", "security/gui", "", "s3", "GUI line")),
|
|
("take over the chair", signing.office_item("takeover", "chair", "s1", "s2", "allocate")),
|
|
("recall a president", signing.office_item("recall", "work/hub", "s3", "", "")),
|
|
("take over a line in the own dimension", signing.office_item("takeover", "identity/oidc", "s2", "s3", "oidc")),
|
|
):
|
|
with self.subTest(name=name):
|
|
status, body = self.sign([item])
|
|
self.assertEqual(status, 200, body)
|
|
self.assertEqual(json.loads(body)["payload"]["items"], [signing.item_hash(item)])
|
|
bad = (
|
|
("capital office", signing.office_item("appoint", "Chair", "", "s3", "w"), 400),
|
|
("three levels", signing.office_item("appoint", "a/b/c", "", "s3", "w"), 400),
|
|
("climbing office", signing.office_item("appoint", "../x", "", "s3", "w"), 400),
|
|
("bare group", signing.office_item("appoint", "work", "", "s3", "w"), 400),
|
|
("unknown session", signing.office_item("appoint", "security/gui", "", "s9", "w"), 400),
|
|
("pseudo session", signing.office_item("appoint", "security/gui", "", "name:Docs", "w"), 400),
|
|
("the operator", signing.office_item("appoint", "security/gui", "", "Operator", "w"), 400),
|
|
("unknown action", {**signing.office_item("appoint", "security/gui", "", "s3", "w"), "action": "fire"}, 400),
|
|
("empty work", signing.office_item("appoint", "security/gui", "", "s3", " "), 400),
|
|
("two lines of work", signing.office_item("appoint", "security/gui", "", "s3", "a\nb"), 400),
|
|
("long work", signing.office_item("appoint", "security/gui", "", "s3", "x" * 301), 400),
|
|
("recall with a successor", signing.office_item("recall", "work/hub", "s3", "s2", ""), 400),
|
|
("extra key", {**signing.office_item("recall", "work/hub", "s3", "", ""), "command": "rm -rf ~"}, 400),
|
|
("missing key", {key_name: value for key_name, value in signing.office_item("recall", "work/hub", "s3", "", "").items() if key_name != "holder"}, 400),
|
|
("number", {**signing.office_item("recall", "work/hub", "s3", "", ""), "holder": 3}, 400),
|
|
("held office", signing.office_item("appoint", "identity/oidc", "", "s3", "w"), 409),
|
|
("holder changed", signing.office_item("takeover", "chair", "s2", "s3", "w"), 409),
|
|
("vacant recall", signing.office_item("recall", "security/gui", "", "", ""), 400),
|
|
("option as session", signing.office_item("appoint", "security/gui", "", "--all", "w"), 400),
|
|
("successor is the holder", signing.office_item("takeover", "chair", "s1", "s1", "w"), 400),
|
|
("second line of a dimension", signing.office_item("appoint", "identity/saml", "", "s2", "w"), 400),
|
|
)
|
|
for name, item, expected in bad:
|
|
with self.subTest(name=name):
|
|
self.assertEqual(self.sign([item])[0], expected)
|
|
item = signing.office_item("appoint", "security/gui", "", "s3", "GUI line")
|
|
self.assertEqual(self.sign([item, item])[0], 400)
|
|
|
|
def test_a_signed_office_becomes_a_job_without_any_command(self):
|
|
item = signing.office_item("takeover", "chair", "s1", "s2", "allocate")
|
|
signer = self.pin()
|
|
proof = signer.proof(self.prepare([item])["payload"], self.origin)
|
|
self.assertEqual(self.post_json("/api/offices", {"items": [item], "proof": None}, self.guard(self.host))[0], 400)
|
|
self.assertEqual(self.post_json("/api/offices", {"items": [item], "proof": proof}, {"Host": self.host})[0], 403)
|
|
self.assertEqual(self.post_json("/api/offices", {"items": [{**item, "holder": "s3"}], "proof": proof}, self.guard(self.host))[0], 409)
|
|
status, _, body = self.post_json("/api/offices", {"items": [item], "proof": proof}, self.guard(self.host))
|
|
self.assertEqual(status, 202, body)
|
|
job_id = json.loads(body)["id"]
|
|
written = self.offices / "jobs" / f"{job_id}.json"
|
|
job = json.loads(written.read_text(encoding="utf-8"))
|
|
self.assertEqual(sorted(job), ["created", "id", "items", "proof", "v"])
|
|
self.assertEqual(job["items"], [{key_name: item[key_name] for key_name in ("action", "office", "holder", "session", "work")}])
|
|
self.assertEqual(job["proof"], proof)
|
|
self.assertNotIn("command", written.read_text(encoding="utf-8"))
|
|
self.assertEqual((written.stat().st_mode & 0o777, (self.offices / "jobs").stat().st_mode & 0o777), (0o600, 0o700))
|
|
self.assertEqual(json.loads(self.get(f"/api/offices/{job_id}")[2])["status"], "queued")
|
|
self.assertEqual(self.get("/api/offices/0000000000000000")[0], 404)
|
|
self.assertEqual(self.get("/api/offices")[0], 405)
|
|
result = {"id": job_id, "finished": time.time(), "items": [{**job["items"][0], "status": "done", "reason": ""}]}
|
|
(self.offices / "results" / f"{job_id}.json").write_text(json.dumps(result), encoding="utf-8")
|
|
self.assertEqual(json.loads(self.get(f"/api/offices/{job_id}")[2])["status"], "done")
|
|
|
|
|
|
class TestHostOffices(unittest.TestCase):
|
|
def setUp(self):
|
|
tmp = tempfile.TemporaryDirectory()
|
|
self.addCleanup(tmp.cleanup)
|
|
base = Path(tmp.name)
|
|
self.council = base / "council"
|
|
self.council.mkdir(mode=0o700)
|
|
self.home = base / "home"
|
|
sessions = self.home / ".claude" / "sessions"
|
|
sessions.mkdir(parents=True)
|
|
for sid, name in (("s1", "One"), ("s2", "Two")):
|
|
(sessions / f"{sid}.json").write_text(json.dumps({"sessionId": sid, "name": name}), encoding="utf-8")
|
|
self.jobs, self.results = base / "jobs", base / "results"
|
|
self.jobs.mkdir()
|
|
self.results.mkdir()
|
|
self.approvers = base / "config" / "approvers.json"
|
|
self.trust = verifier.Trust(approvers=self.approvers, replay=base / "replay" / "offices.json", origin=ORIGIN)
|
|
self.signer = key(-7, "main")
|
|
self.signer.pin(self.approvers, ORIGIN)
|
|
self.runner = host.Offices(self.trust, self.council, COUNCIL_SCRIPT, self.home)
|
|
|
|
def proof(self, items: list[dict], signer) -> dict:
|
|
hashes = [signing.item_hash(signing.office_item(**item)) for item in items]
|
|
return signer.proof(signing.approval_payload(hashes, secrets.token_hex(16), int(time.time()) + 600), ORIGIN)
|
|
|
|
def run_job(self, items: list[dict], proof: object) -> dict:
|
|
job_id = secrets.token_hex(8)
|
|
(self.jobs / f"{job_id}.json").write_text(json.dumps({"v": 1, "id": job_id, "created": "x", "items": items, "proof": proof}), encoding="utf-8")
|
|
self.assertEqual(host.cycle(self.jobs, self.results, self.runner), 1)
|
|
self.assertEqual(list(self.jobs.iterdir()), [])
|
|
return json.loads((self.results / f"{job_id}.json").read_text(encoding="utf-8"))
|
|
|
|
def signed(self, item: dict) -> dict:
|
|
return self.run_job([item], self.proof([item], self.signer))
|
|
|
|
def holder(self, office: str) -> dict | None:
|
|
path = self.council / office / "claim.json"
|
|
return json.loads(path.read_text(encoding="utf-8")) if path.exists() else None
|
|
|
|
def files(self) -> list[str]:
|
|
return sorted(str(path.relative_to(self.council)) for path in self.council.rglob("*"))
|
|
|
|
def test_appoint_take_over_and_recall_run_the_council_script_for_the_operator(self):
|
|
appoint = {"action": "appoint", "office": "chair", "holder": "", "session": "s1", "work": "allocate"}
|
|
self.assertEqual([(entry["status"], entry["code"]) for entry in self.signed(appoint)["items"]], [("done", 0)])
|
|
self.assertEqual({key_name: self.holder("chair")[key_name] for key_name in ("session", "runtime", "name", "work")}, {"session": "s1", "runtime": "claude-code", "name": "One", "work": "allocate"})
|
|
takeover = {"action": "takeover", "office": "chair", "holder": "s1", "session": "s2", "work": "allocate more"}
|
|
self.assertEqual(self.signed(takeover)["items"][0]["status"], "done")
|
|
self.assertEqual((self.holder("chair")["session"], self.holder("chair")["name"]), ("s2", "Two"))
|
|
asleep = {"action": "appoint", "office": "security/gui", "holder": "", "session": "s9", "work": "gui line"}
|
|
self.assertEqual(self.signed(asleep)["items"][0]["status"], "done")
|
|
self.assertEqual((self.holder("security/gui")["session"], self.holder("security/gui")["runtime"]), ("s9", "other"))
|
|
recall = {"action": "recall", "office": "chair", "holder": "s2", "session": "", "work": ""}
|
|
self.assertEqual(self.signed(recall)["items"][0]["status"], "done")
|
|
self.assertIsNone(self.holder("chair"))
|
|
president = {"action": "appoint", "office": "work/new", "holder": "", "session": "s1", "work": "build it"}
|
|
self.assertEqual(self.signed(president)["items"][0]["status"], "done")
|
|
row = json.loads((self.council / "rasci.json").read_text(encoding="utf-8"))["work/new"]
|
|
self.assertEqual((row["worker"], row["description"], "workdir" in row, "branch" in row), ("One", "build it", False, False))
|
|
|
|
def test_every_doubtful_item_is_refused_and_changes_nothing(self):
|
|
appoint = {"action": "appoint", "office": "chair", "holder": "", "session": "s1", "work": "allocate"}
|
|
self.signed({"action": "appoint", "office": "identity/oidc", "holder": "", "session": "s2", "work": "oidc"})
|
|
rule = self.signer.proof(signing.rule_payload(secrets.token_hex(8), ["office"], "", "*", "*", int(time.time()) + 600), ORIGIN)
|
|
outside = self.council.parent / "outside"
|
|
(outside / "gui").mkdir(parents=True)
|
|
cases = (
|
|
("bad signature", appoint, self.proof([appoint], key(-7, "intruder")), "no valid operator signature"),
|
|
("missing signature", appoint, None, "no signature"),
|
|
("rule instead of approval", appoint, rule, "no valid operator signature"),
|
|
("other item signed", appoint, self.proof([{**appoint, "session": "s2"}], self.signer), "does not list this item"),
|
|
("holder changed", {**appoint, "office": "identity/oidc"}, self.proof([{**appoint, "office": "identity/oidc"}], self.signer), "holder changed"),
|
|
)
|
|
for name, item, proof, reason in cases:
|
|
with self.subTest(name=name):
|
|
before = self.files()
|
|
result = self.run_job([item], proof)
|
|
self.assertEqual([entry["status"] for entry in result["items"]], ["refused"])
|
|
self.assertIn(reason, result["items"][0]["reason"])
|
|
self.assertEqual(self.files(), before)
|
|
(self.council / "security").symlink_to(outside)
|
|
linked = {**appoint, "office": "security/gui"}
|
|
result = self.signed(linked)
|
|
self.assertEqual(result["items"][0]["status"], "refused")
|
|
self.assertIn("link", result["items"][0]["reason"])
|
|
self.assertEqual(list(outside.rglob("*")), [outside / "gui"])
|
|
(self.council / "security").unlink()
|
|
self.council.chmod(0o777)
|
|
result = self.signed(appoint)
|
|
self.assertEqual(result["items"][0]["status"], "refused")
|
|
self.assertIn("others can write", result["items"][0]["reason"])
|
|
self.council.chmod(0o700)
|
|
self.assertIsNone(self.holder("chair"))
|
|
|
|
def test_the_runner_passes_no_flag_and_checks_the_holder_in_the_removal_itself(self):
|
|
self.signed({"action": "appoint", "office": "chair", "holder": "", "session": "s1", "work": "allocate"})
|
|
takeover = {"action": "takeover", "office": "chair", "holder": "s1", "session": "s2", "work": "allocate"}
|
|
recall = {"action": "recall", "office": "chair", "holder": "s1", "session": "", "work": ""}
|
|
self.assertNotIn("--operator", self.runner.command(takeover)[0])
|
|
swapped = {**self.holder("chair"), "session": "s9"}
|
|
(self.council / "chair" / "claim.json").write_text(json.dumps(swapped), encoding="utf-8")
|
|
with mock.patch.object(host, "holder_of", return_value="s1"):
|
|
for item in (takeover, recall):
|
|
with self.subTest(action=item["action"]):
|
|
result = self.signed(item)["items"][0]
|
|
self.assertEqual(result["status"], "refused", result)
|
|
self.assertIn("holder changed", result["reason"])
|
|
self.assertEqual(self.holder("chair"), swapped)
|
|
self.assertEqual(self.files(), ["chair", "chair/claim.json"])
|
|
|
|
def test_a_claim_council_would_not_read_is_never_reported_recalled(self):
|
|
(self.council / "chair").mkdir()
|
|
(self.council / "chair" / "claim.json").write_text(json.dumps({"session": "s1"}), encoding="utf-8")
|
|
result = self.signed({"action": "recall", "office": "chair", "holder": "s1", "session": "", "work": ""})["items"][0]
|
|
self.assertNotEqual(result["status"], "done", result)
|
|
self.assertEqual(self.files(), ["chair", "chair/claim.json"])
|
|
|
|
def test_a_job_that_is_a_link_a_fifo_or_too_large_runs_nothing(self):
|
|
appoint = {"action": "appoint", "office": "chair", "holder": "", "session": "s1", "work": "allocate"}
|
|
linked, fifo, large = (secrets.token_hex(8) for _ in range(3))
|
|
planted = self.council.parent / "planted.json"
|
|
planted.write_text(json.dumps({"v": 1, "id": linked, "created": "x", "items": [appoint], "proof": self.proof([appoint], self.signer)}), encoding="utf-8")
|
|
(self.jobs / f"{linked}.json").symlink_to(planted)
|
|
os.mkfifo(self.jobs / f"{fifo}.json", 0o600)
|
|
(self.jobs / f"{large}.json").write_text(" " * (host.READ_LIMIT + 1), encoding="utf-8")
|
|
self.assertEqual(host.cycle(self.jobs, self.results, self.runner), 3)
|
|
for job_id in (linked, fifo, large):
|
|
with self.subTest(job=job_id):
|
|
result = json.loads((self.results / f"{job_id}.json").read_text(encoding="utf-8"))
|
|
self.assertEqual(result["items"], [])
|
|
self.assertIn("unreadable job", result["error"])
|
|
self.assertEqual((list(self.jobs.iterdir()), self.files()), ([], []))
|
|
self.assertTrue(planted.is_file())
|
|
|
|
def test_a_signature_runs_once_and_a_malformed_job_nothing(self):
|
|
appoint = {"action": "appoint", "office": "chair", "holder": "", "session": "s1", "work": "allocate"}
|
|
proof = self.proof([appoint], self.signer)
|
|
self.assertEqual(self.run_job([appoint], proof)["items"][0]["status"], "done")
|
|
self.signed({"action": "recall", "office": "chair", "holder": "s1", "session": "", "work": ""})
|
|
again = self.run_job([appoint], proof)
|
|
self.assertEqual(again["items"][0]["status"], "refused")
|
|
self.assertIn("already used", again["items"][0]["reason"])
|
|
for name, items in (
|
|
("command smuggled in", [{**appoint, "command": "rm -rf ~"}]),
|
|
("climbing office", [{**appoint, "office": "../x"}]),
|
|
("unknown action", [{**appoint, "action": "fire"}]),
|
|
("option as session", [{**appoint, "session": "--all"}]),
|
|
("two lines of work", [{**appoint, "work": "a\nb"}]),
|
|
("recall with work", [{"action": "recall", "office": "chair", "holder": "s1", "session": "", "work": "x"}]),
|
|
("no items", []),
|
|
):
|
|
with self.subTest(name=name):
|
|
result = self.run_job(items, None)
|
|
self.assertEqual(result["items"], [])
|
|
self.assertIn("malformed job", result["error"])
|
|
self.assertIsNone(self.holder("chair"))
|
|
|
|
def test_the_unit_runs_the_script_once_over_the_job_directory(self):
|
|
appoint = {"action": "appoint", "office": "chair", "holder": "", "session": "s1", "work": "allocate"}
|
|
job_id = secrets.token_hex(8)
|
|
(self.jobs / f"{job_id}.json").write_text(json.dumps({"v": 1, "id": job_id, "created": "x", "items": [appoint], "proof": self.proof([appoint], self.signer)}), encoding="utf-8")
|
|
(self.jobs / "stray.tmp").write_text("x", encoding="utf-8")
|
|
trust = ["--approvers", str(self.approvers), "--replay", str(self.trust.replay)]
|
|
command = [sys.executable, str(OFFICES), "--port", ORIGIN.rsplit(":", 1)[1], "--jobs", str(self.jobs), "--results", str(self.results), *trust, "--council", str(self.council), "--script", str(COUNCIL_SCRIPT)]
|
|
done = subprocess.run(command, capture_output=True, text=True, timeout=60, check=False, env={"PATH": "/usr/bin:/bin", "HOME": str(self.home)})
|
|
self.assertEqual(done.returncode, 0, done.stderr)
|
|
self.assertEqual(list(self.jobs.iterdir()), [])
|
|
result = json.loads((self.results / f"{job_id}.json").read_text(encoding="utf-8"))
|
|
self.assertEqual(result["items"][0]["status"], "done", result)
|
|
self.assertEqual((self.results / f"{job_id}.json").stat().st_mode & 0o777, 0o600)
|
|
self.assertEqual(self.holder("chair")["session"], "s1")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|