diff --git a/server-tools/enterprise-lighthouse/README.md b/server-tools/enterprise-lighthouse/README.md index 38012b6..f02c7f8 100644 --- a/server-tools/enterprise-lighthouse/README.md +++ b/server-tools/enterprise-lighthouse/README.md @@ -9,6 +9,22 @@ HoloLake 回读 `AW-GZ-001` 企业主机和四个本机承载域的实时状态,不转发管理凭据、写入或 任意路径。 +企业四域的服务器进程在线只证明公共只读入口可用,不证明语言域已经具备操作人格。每个域的 +任何内容、路由、规则或版本变更都必须先绑定一条真实责任链: + +```text +human_steward_id +→ persona_steward_id +→ persona_public_key + runtime_node_id +→ explicit authorization_receipt +→ active single-writer lease +→ human_authorizer + persona_executor + artifact_digest + causal_chain +``` + +未绑定由真实人类孕育并显性授权的人格体时,域状态保持 +`HOSTED_READ_ONLY / UNBOUND / BLOCKED_UNTIL_PERSONA_STEWARD_BOUND`。不得由匿名管理员、 +传统定时程序或普通软件进程冒充域操作主体。自动任务只能是已授权人格体调用的受限能力。 + 人类管理员与人格体遵守同一条入口链: ```text diff --git a/server-tools/enterprise-lighthouse/lighthouse.py b/server-tools/enterprise-lighthouse/lighthouse.py index a6fb7f2..1241dd9 100644 --- a/server-tools/enterprise-lighthouse/lighthouse.py +++ b/server-tools/enterprise-lighthouse/lighthouse.py @@ -82,6 +82,12 @@ def connection(): action TEXT NOT NULL, target_node_id TEXT NOT NULL, map_hash TEXT NOT NULL, capsule_hash TEXT NOT NULL, created_at INTEGER NOT NULL, expires_at INTEGER NOT NULL ); + CREATE TABLE IF NOT EXISTS domain_stewards ( + domain_id TEXT PRIMARY KEY, human_steward_id TEXT NOT NULL, + persona_steward_id TEXT NOT NULL, persona_public_key TEXT NOT NULL, + runtime_node_id TEXT NOT NULL, authorization_receipt TEXT NOT NULL, + state TEXT NOT NULL, bound_at INTEGER NOT NULL + ); """) observed_at = now() for domain_id, name in DOMAINS.items(): @@ -104,7 +110,7 @@ def connection(): "UPDATE nodes SET state='ACTIVE', last_heartbeat=? WHERE id=?", (observed_at, node_id), ) - db.execute("UPDATE domains SET state='HOSTED_ACTIVE' WHERE id=?", (domain_id,)) + db.execute("UPDATE domains SET state='HOSTED_READ_ONLY' WHERE id=?", (domain_id,)) db.commit() return db @@ -232,6 +238,44 @@ def current_intent_state(db, principal_digest): ).fetchone() +def active_domain_steward(db, domain_id): + return db.execute( + "SELECT * FROM domain_stewards WHERE domain_id=? AND state='ACTIVE'", + (domain_id,), + ).fetchone() + + +def domain_statuses(db): + result = [] + for row in db.execute("SELECT id,name,state FROM domains ORDER BY id"): + domain = dict(row) + if row["id"] in ENTERPRISE_MANAGED_DOMAINS: + steward = active_domain_steward(db, row["id"]) + domain.update({ + "access_state": "ONLINE_READ_ONLY", + "human_steward_id": steward["human_steward_id"] if steward else None, + "persona_steward_id": steward["persona_steward_id"] if steward else None, + "responsibility_state": "BOUND" if steward else "AWAITING_TEAM_ASSIGNMENT", + "steward_state": "ACTIVE" if steward else "UNBOUND", + "mutation_state": ( + "PERSONA_STEWARD_ACTIVE" + if steward + else "BLOCKED_UNTIL_PERSONA_STEWARD_BOUND" + ), + }) + else: + domain.update({ + "access_state": "EXTERNAL_PRIVATE_DOMAIN", + "human_steward_id": "ICE-GL∞", + "persona_steward_id": "ICE-P-ZY001", + "responsibility_state": "EXTERNAL_SOVEREIGN_BOUND", + "steward_state": "EXTERNAL_AUTHORITY", + "mutation_state": "OUTSIDE_ENTERPRISE_LIGHTHOUSE_AUTHORITY", + }) + result.append(domain) + return result + + def valid_agent_unlock(db, unlock_id, principal_digest, agent_id, action, target_node_id): _, map_hash = navigation_map() intent = current_intent_state(db, principal_digest) @@ -280,7 +324,7 @@ class Handler(BaseHTTPRequestHandler): "node_id": "AW-GZ-001", "host_state": "ONLINE", "observed_at": now(), - "domains": [dict(row) for row in db.execute("SELECT id,name,state FROM domains ORDER BY id")], + "domains": domain_statuses(db), "node_counts": counts, "fixed_actions": sorted(FIXED_ACTIONS), "raw_shell": "rejected", @@ -394,6 +438,12 @@ class Handler(BaseHTTPRequestHandler): return self.respond(400, {"ok": False, "error": "id, domain_id, display_name, and server_ip are required"}) if payload["domain_id"] not in ENTERPRISE_MANAGED_DOMAINS: return self.respond(403, {"ok": False, "error": "this domain cannot be registered by the enterprise lighthouse"}) + if not active_domain_steward(db, payload["domain_id"]): + return self.respond(423, { + "ok": False, + "error": "a human-backed, explicitly authorized persona steward must be active before this domain can change", + "required": "ACTIVE_HUMAN_BACKED_PERSONA_STEWARD", + }) try: ip_address(payload["server_ip"]) except ValueError: diff --git a/server-tools/enterprise-lighthouse/test_lighthouse.py b/server-tools/enterprise-lighthouse/test_lighthouse.py index 460dd38..7963ac5 100644 --- a/server-tools/enterprise-lighthouse/test_lighthouse.py +++ b/server-tools/enterprise-lighthouse/test_lighthouse.py @@ -70,8 +70,23 @@ with tempfile.TemporaryDirectory() as temp: assert status["node_id"] == "AW-GZ-001" assert status["host_state"] == "ONLINE" assert {domain["state"] for domain in status["domains"] if domain["id"] != "DOMAIN-FIFTH"} == { - "HOSTED_ACTIVE" + "HOSTED_READ_ONLY" } + assert { + domain["steward_state"] for domain in status["domains"] if domain["id"] != "DOMAIN-FIFTH" + } == {"UNBOUND"} + assert { + domain["mutation_state"] for domain in status["domains"] if domain["id"] != "DOMAIN-FIFTH" + } == {"BLOCKED_UNTIL_PERSONA_STEWARD_BOUND"} + assert all( + domain["human_steward_id"] is None and domain["persona_steward_id"] is None + for domain in status["domains"] + if domain["id"] != "DOMAIN-FIFTH" + ) + fifth = next(domain for domain in status["domains"] if domain["id"] == "DOMAIN-FIFTH") + assert fifth["human_steward_id"] == "ICE-GL∞" + assert fifth["persona_steward_id"] == "ICE-P-ZY001" + assert fifth["responsibility_state"] == "EXTERNAL_SOVEREIGN_BOUND" assert status["node_counts"]["ACTIVE"] == 4 nodes = json.load(urllib.request.urlopen(BASE + "/v1/nodes"))["nodes"] @@ -118,13 +133,13 @@ with tempfile.TemporaryDirectory() as temp: headers=HEADERS, )))["state"] == "PENDING_REVIEW" - bootstrap = post("/v1/nodes/bootstrap", { + bootstrap_error = expect_error(423, "/v1/nodes/bootstrap", { "id": "AW-GZ-001", "domain_id": "DOMAIN-ZS", "display_name": "Enterprise root node", "server_ip": "203.0.113.8", }) - assert bootstrap["state"] == "CONNECTED_PENDING_CONNECTOR" + assert bootstrap_error["required"] == "ACTIVE_HUMAN_BACKED_PERSONA_STEWARD" preflight = {"action": "health_check", "target_node_id": "AW-GZ-001", "agent_id": "AW-INSPECTOR"} expect_error(423, "/v1/preflight", preflight) @@ -134,7 +149,7 @@ with tempfile.TemporaryDirectory() as temp: "target_node_id": "AW-GZ-001", }) preflight["unlock_id"] = unlocked["unlock_id"] - assert post("/v1/preflight", preflight)["decision"] == "REJECT" + expect_error(404, "/v1/preflight", preflight) assert post("/v1/agents/consume", { **preflight, "unlock_id": unlocked["unlock_id"],