feat(enterprise): route four domains through lighthouse

This commit is contained in:
冰朔 2026-08-16 20:27:52 +08:00
commit c058974bba
12 changed files with 707 additions and 20 deletions

View file

@ -9,3 +9,18 @@
当前阶段只声明入口与边界;“已登记”不等于对应责任主体已经接受、人格体已经出生或
域内全部功能已经实现。
## 身份、关系与责任
`enterprise_identity_service.py` 是运行于企业 Linux 物理层之上的灯塔服务,不要求
企业服务器改装一套新的物理操作系统。它只监听回环地址,由 `guanghu.chat` 的精确
API 路由对客户端开放:
- 编号解析:把 TCS-GL 人类编号路由到工作域、企业账号和私有仓库;
- 关系确认:由人类确认自己与人格体的认领关系;
- 责任回执:独立记录对域责任的接受、拒绝、延期或修改后接受;
- 仓库验证:登录凭证只透传给同机 Forgejo 验证,不写入数据库或日志。
`AGE` 只表示人格体物种,不能作为任何人格体的个体身份编号。现有 `PER-*` 作为历史
和当前可核验的个体身份引用保留;企业四域正式人格体身份编号前缀由光湖团队另行治理,
服务不会擅自生成。第五域现行个体身份编号继续使用 `ICE-P-*`

View file

@ -0,0 +1,116 @@
#!/usr/bin/env python3
"""Idempotently create the five private enterprise work repositories.
Run on the enterprise node with a short-lived Forgejo admin token stored in a
root-readable file. The token is never printed. Existing repositories are
inspected and preserved; a public or wrongly-owned collision fails closed.
"""
from __future__ import annotations
import argparse
import json
import urllib.error
import urllib.request
from pathlib import Path
def request(base: str, token: str, method: str, path: str, body: dict | None = None):
data = json.dumps(body).encode() if body is not None else None
call = urllib.request.Request(base + path, data=data, method=method)
call.add_header("Authorization", f"token {token}")
call.add_header("Accept", "application/json")
if data is not None:
call.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(call, timeout=20) as response:
raw = response.read()
return response.status, json.loads(raw) if raw else {}
except urllib.error.HTTPError as error:
raw = error.read()
detail = json.loads(raw) if raw else {}
return error.code, detail
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--registry", required=True)
parser.add_argument("--token-file", required=True)
parser.add_argument("--token-name", required=True)
parser.add_argument("--receipt", required=True)
parser.add_argument("--base", default="http://127.0.0.1:3341/api/v1")
args = parser.parse_args()
registry = json.loads(Path(args.registry).read_text(encoding="utf-8"))
token = Path(args.token_file).read_text(encoding="utf-8").strip()
if len(token) < 32:
raise SystemExit("short-lived Forgejo token unavailable")
results = []
completed = False
try:
for human in registry["humans"]:
owner, name = human["repository"].split("/", 1)
status, existing = request(args.base, token, "GET", f"/repos/{owner}/{name}")
action = "PRESERVED"
if status == 404:
status, existing = request(
args.base,
token,
"POST",
f"/admin/users/{owner}/repos",
{
"name": name,
"description": f"{human['display_name']} · {human['responsibility_domain']} 独立工作仓库",
"private": True,
"auto_init": True,
"default_branch": "main",
"gitignores": "",
"issue_labels": "",
"license": "",
"readme": "Default",
},
)
action = "CREATED"
if status not in (200, 201):
raise RuntimeError(f"repository provision failed for {owner}/{name}: HTTP {status}")
actual_owner = existing.get("owner", {}).get("login")
if actual_owner != owner or existing.get("private") is not True:
raise RuntimeError(f"repository boundary invalid for {owner}/{name}")
results.append(
{
"human_number": human["human_number"],
"repository": f"{owner}/{name}",
"private": True,
"action": action,
}
)
completed = True
finally:
# Revoke the bootstrap token after success. On failure it remains in the
# root-only token file so an operator can inspect and retry deliberately.
if completed:
revoke_status, _ = request(
args.base,
token,
"DELETE",
f"/admin/users/bingshuo/tokens/{args.token_name}",
)
if revoke_status not in (204, 404):
raise RuntimeError(f"bootstrap token revocation failed: HTTP {revoke_status}")
receipt = {
"schema": "guanghu.enterprise-private-repository-bootstrap-receipt/v1",
"state": "PASS",
"forgejo": "guanghu.chat/code",
"repositories": results,
"token_revoked": True,
"shared_initial_password_used": False,
"existing_user_passwords_modified": False,
}
Path(args.receipt).write_text(json.dumps(receipt, ensure_ascii=False, indent=2) + "\n")
print(json.dumps(receipt, ensure_ascii=False))
if __name__ == "__main__":
main()

View file

@ -0,0 +1,308 @@
#!/usr/bin/env python3
"""HoloLake enterprise identity, relationship and responsibility receipt service.
The service binds only to loopback. Nginx exposes exact routes. Credentials are
verified against the local Forgejo API and are never stored or logged.
"""
from __future__ import annotations
import base64
import hashlib
import hmac
import json
import os
import re
import sqlite3
import time
import urllib.error
import urllib.parse
import urllib.request
import uuid
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
BIND = os.environ.get("GH_ENTERPRISE_IDENTITY_BIND", "127.0.0.1")
PORT = int(os.environ.get("GH_ENTERPRISE_IDENTITY_PORT", "8032"))
DB_PATH = os.environ.get(
"GH_ENTERPRISE_IDENTITY_DB",
"/var/lib/guanghu-enterprise-identity/identity.sqlite3",
)
REGISTRY_PATH = os.environ.get(
"GH_ENTERPRISE_IDENTITY_REGISTRY",
"/etc/guanghu/enterprise-identity-registry.json",
)
FORGEJO_USER_API = os.environ.get(
"GH_ENTERPRISE_FORGEJO_USER_API", "http://127.0.0.1:3341/api/v1/user"
)
RECEIPT_KEY = os.environ.get("GH_ENTERPRISE_RECEIPT_KEY", "")
MAX_BODY = 16_384
USERNAME = re.compile(r"^[A-Za-z0-9_-]{1,40}$")
DECISIONS = {"ACCEPT", "REJECT", "DEFER", "ACCEPT_WITH_CHANGES"}
def now() -> int:
return int(time.time())
def canonical(value: object) -> bytes:
return json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode()
def load_registry() -> dict:
registry = json.loads(Path(REGISTRY_PATH).read_text(encoding="utf-8"))
if registry.get("schema") != "guanghu.enterprise-identity-registry/v1":
raise ValueError("enterprise identity registry schema invalid")
humans = registry.get("humans")
if not isinstance(humans, list) or not humans:
raise ValueError("enterprise identity registry is empty")
numbers = [item.get("human_number") for item in humans]
usernames = [item.get("username") for item in humans]
if len(numbers) != len(set(numbers)) or len(usernames) != len(set(usernames)):
raise ValueError("enterprise identity registry identities must be unique")
for item in humans:
if not USERNAME.fullmatch(str(item.get("username", ""))):
raise ValueError("enterprise username invalid")
for persona in item.get("personas", []):
if persona.get("species") != "AGE" or str(persona.get("current_persona_identity", "")).startswith("AGE-"):
raise ValueError("AGE is a species and cannot be used as a persona identity number")
return registry
def database() -> sqlite3.Connection:
path = Path(DB_PATH)
path.parent.mkdir(parents=True, exist_ok=True)
db = sqlite3.connect(path)
db.row_factory = sqlite3.Row
db.executescript(
"""
PRAGMA journal_mode=WAL;
PRAGMA foreign_keys=ON;
CREATE TABLE IF NOT EXISTS relationship_receipts (
receipt_id TEXT PRIMARY KEY,
idempotency_key TEXT NOT NULL UNIQUE,
human_number TEXT NOT NULL,
username TEXT NOT NULL,
registry_version TEXT NOT NULL,
decision TEXT NOT NULL,
observed_at INTEGER NOT NULL,
receipt_hash TEXT NOT NULL,
receipt_signature TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS responsibility_receipts (
receipt_id TEXT PRIMARY KEY,
idempotency_key TEXT NOT NULL UNIQUE,
human_number TEXT NOT NULL,
username TEXT NOT NULL,
responsibility_domain TEXT NOT NULL,
responsibility_version TEXT NOT NULL,
decision TEXT NOT NULL,
note TEXT NOT NULL,
observed_at INTEGER NOT NULL,
receipt_hash TEXT NOT NULL,
receipt_signature TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS audit (
sequence INTEGER PRIMARY KEY AUTOINCREMENT,
observed_at INTEGER NOT NULL,
kind TEXT NOT NULL,
human_number_hash TEXT NOT NULL,
receipt_id TEXT NOT NULL
);
"""
)
return db
def find_human(registry: dict, number: str) -> dict | None:
encoded = number.encode("utf-8")
return next(
(
item
for item in registry["humans"]
if hmac.compare_digest(item["human_number"].encode("utf-8"), encoded)
),
None,
)
def parse_basic(header: str) -> tuple[str, str] | None:
if not header.startswith("Basic "):
return None
try:
decoded = base64.b64decode(header[6:], validate=True).decode("utf-8")
username, password = decoded.split(":", 1)
except (ValueError, UnicodeDecodeError):
return None
if not USERNAME.fullmatch(username) or not password or len(password) > 512:
return None
return username, password
def verify_forgejo(username: str, password: str) -> bool:
request = urllib.request.Request(FORGEJO_USER_API)
credential = base64.b64encode(f"{username}:{password}".encode()).decode()
request.add_header("Authorization", f"Basic {credential}")
request.add_header("Accept", "application/json")
try:
with urllib.request.urlopen(request, timeout=10) as response:
body = json.load(response)
return response.status == 200 and hmac.compare_digest(str(body.get("login", "")), username)
except (urllib.error.HTTPError, urllib.error.URLError, TimeoutError, ValueError):
return False
def signed_receipt(payload: dict) -> dict:
if len(RECEIPT_KEY) < 32:
raise RuntimeError("receipt signing key unavailable")
body = canonical(payload)
receipt_hash = hashlib.sha256(body).hexdigest()
signature = hmac.new(RECEIPT_KEY.encode(), body, hashlib.sha256).hexdigest()
return {**payload, "receipt_hash": receipt_hash, "receipt_signature": signature}
def public_projection(registry: dict, human: dict, db: sqlite3.Connection | None = None) -> dict:
projection = {
"status": "RESOLVED",
"canonical_id": human["human_number"],
"subject": {
"id": human["human_number"],
"name": human["display_name"],
"domain": human["responsibility_domain"],
},
"work_entry": {
"domain": registry["work_entry_domain"],
"channel": registry["work_entry_channel"],
},
"repository_binding": {
"host": "guanghu.chat",
"username": human["username"],
"repository": human["repository"],
"private": True,
},
"persona_relationships": human["personas"],
"persona_identity_governance": registry["persona_identity_governance"],
"registry_version": registry["version"],
}
if db is not None:
relationship = db.execute(
"SELECT decision,observed_at,receipt_hash FROM relationship_receipts WHERE human_number=? ORDER BY observed_at DESC LIMIT 1",
(human["human_number"],),
).fetchone()
responsibility = db.execute(
"SELECT decision,observed_at,receipt_hash,responsibility_version FROM responsibility_receipts WHERE human_number=? ORDER BY observed_at DESC LIMIT 1",
(human["human_number"],),
).fetchone()
projection["relationship_confirmation"] = dict(relationship) if relationship else None
projection["responsibility_receipt"] = dict(responsibility) if responsibility else None
return projection
class Handler(BaseHTTPRequestHandler):
server_version = "GuanghuEnterpriseIdentity/1.0"
def log_message(self, fmt: str, *args: object) -> None:
# Never include headers or request bodies in logs.
print("[enterprise-identity] " + fmt % args)
def respond(self, status: int, body: dict) -> None:
encoded = json.dumps(body, ensure_ascii=False).encode()
self.send_response(status)
self.send_header("Content-Type", "application/json; charset=utf-8")
self.send_header("Content-Length", str(len(encoded)))
self.send_header("Cache-Control", "no-store")
self.send_header("X-Content-Type-Options", "nosniff")
self.end_headers()
self.wfile.write(encoded)
def body(self) -> dict:
length = int(self.headers.get("Content-Length", "0"))
if length < 1 or length > MAX_BODY:
raise ValueError("request body size invalid")
value = json.loads(self.rfile.read(length).decode())
if not isinstance(value, dict):
raise ValueError("JSON object required")
return value
def authenticated_human(self, registry: dict, payload: dict) -> tuple[dict, str] | None:
credentials = parse_basic(self.headers.get("Authorization", ""))
number = str(payload.get("human_number", ""))
human = find_human(registry, number)
if not credentials or not human:
return None
username, password = credentials
if not hmac.compare_digest(username, human["username"]) or not verify_forgejo(username, password):
return None
return human, username
def do_GET(self) -> None:
try:
registry = load_registry()
except (OSError, ValueError, json.JSONDecodeError) as error:
return self.respond(503, {"ok": False, "error": f"registry unavailable: {error}"})
parsed = urllib.parse.urlparse(self.path)
if parsed.path == "/health":
return self.respond(200, {"ok": True, "service": "guanghu-enterprise-identity", "registry_version": registry["version"], "age_species": "AGE", "valid_age_individual_numbers": 0})
if parsed.path == "/v1/resolve":
number = urllib.parse.parse_qs(parsed.query).get("id", [""])[0]
human = find_human(registry, number)
return self.respond(200 if human else 404, public_projection(registry, human) if human else {"status": "NOT_FOUND"})
return self.respond(404, {"ok": False, "error": "not found"})
def do_POST(self) -> None:
try:
registry = load_registry()
payload = self.body()
except (OSError, ValueError, json.JSONDecodeError) as error:
return self.respond(400, {"ok": False, "error": str(error)})
authenticated = self.authenticated_human(registry, payload)
if not authenticated:
return self.respond(401, {"ok": False, "error": "enterprise account authentication failed"})
human, username = authenticated
idempotency_key = str(payload.get("idempotency_key", ""))
if not re.fullmatch(r"[A-Za-z0-9_-]{16,96}", idempotency_key):
return self.respond(400, {"ok": False, "error": "valid idempotency_key required"})
db = database()
try:
if self.path == "/v1/relationship-confirmations":
decision = str(payload.get("decision", ""))
if decision not in {"CONFIRM", "REJECT"}:
return self.respond(400, {"ok": False, "error": "relationship decision invalid"})
existing = db.execute("SELECT * FROM relationship_receipts WHERE idempotency_key=?", (idempotency_key,)).fetchone()
if existing:
return self.respond(200, {"ok": True, "idempotent": True, "receipt": dict(existing)})
observed = now()
receipt_id = "GH-REL-" + uuid.uuid4().hex.upper()
receipt = signed_receipt({"receipt_id":receipt_id,"human_number":human["human_number"],"username":username,"registry_version":registry["version"],"decision":decision,"observed_at":observed})
db.execute("INSERT INTO relationship_receipts VALUES (?,?,?,?,?,?,?,?,?)", (receipt_id,idempotency_key,human["human_number"],username,registry["version"],decision,observed,receipt["receipt_hash"],receipt["receipt_signature"]))
db.execute("INSERT INTO audit(observed_at,kind,human_number_hash,receipt_id) VALUES (?,?,?,?)", (observed,"RELATIONSHIP_CONFIRMATION",hashlib.sha256(human["human_number"].encode()).hexdigest(),receipt_id))
db.commit()
return self.respond(201, {"ok": True, "receipt": receipt})
if self.path == "/v1/responsibility-receipts":
decision = str(payload.get("decision", ""))
note = str(payload.get("note", ""))[:1000]
version = str(payload.get("responsibility_version", ""))
if decision not in DECISIONS or not re.fullmatch(r"[0-9]{4}-[0-9]{2}-[0-9]{2}\.[0-9]+", version):
return self.respond(400, {"ok": False, "error": "responsibility decision or version invalid"})
existing = db.execute("SELECT * FROM responsibility_receipts WHERE idempotency_key=?", (idempotency_key,)).fetchone()
if existing:
return self.respond(200, {"ok": True, "idempotent": True, "receipt": dict(existing)})
observed = now()
receipt_id = "GH-RESP-" + uuid.uuid4().hex.upper()
receipt = signed_receipt({"receipt_id":receipt_id,"human_number":human["human_number"],"username":username,"responsibility_domain":human["responsibility_domain"],"responsibility_version":version,"decision":decision,"note":note,"observed_at":observed})
db.execute("INSERT INTO responsibility_receipts VALUES (?,?,?,?,?,?,?,?,?,?,?)", (receipt_id,idempotency_key,human["human_number"],username,human["responsibility_domain"],version,decision,note,observed,receipt["receipt_hash"],receipt["receipt_signature"]))
db.execute("INSERT INTO audit(observed_at,kind,human_number_hash,receipt_id) VALUES (?,?,?,?)", (observed,"RESPONSIBILITY_RECEIPT",hashlib.sha256(human["human_number"].encode()).hexdigest(),receipt_id))
db.commit()
return self.respond(201, {"ok": True, "receipt": receipt})
if self.path == "/v1/me/entry":
return self.respond(200, {"ok": True, "entry": public_projection(registry, human, db)})
return self.respond(404, {"ok": False, "error": "not found"})
finally:
db.close()
if __name__ == "__main__":
load_registry()
if len(RECEIPT_KEY) < 32:
raise SystemExit("GH_ENTERPRISE_RECEIPT_KEY must contain at least 32 characters")
ThreadingHTTPServer((BIND, PORT), Handler).serve_forever()

View file

@ -0,0 +1,58 @@
import importlib.util
import json
import os
import tempfile
import unittest
from pathlib import Path
ROOT = Path(__file__).parent
REGISTRY = ROOT / "registry" / "enterprise-identity-registry.json"
os.environ["GH_ENTERPRISE_IDENTITY_REGISTRY"] = str(REGISTRY)
os.environ["GH_ENTERPRISE_RECEIPT_KEY"] = "test-only-key-that-is-longer-than-32-bytes"
spec = importlib.util.spec_from_file_location("enterprise_identity_service", ROOT / "enterprise_identity_service.py")
service = importlib.util.module_from_spec(spec)
spec.loader.exec_module(service)
class EnterpriseIdentityTests(unittest.TestCase):
def test_age_is_species_and_never_an_individual_identity(self):
registry = service.load_registry()
self.assertEqual(registry["persona_identity_governance"]["species"], "AGE")
self.assertFalse(registry["persona_identity_governance"]["age_is_individual_number_namespace"])
for human in registry["humans"]:
for persona in human["personas"]:
self.assertEqual(persona["species"], "AGE")
self.assertFalse(persona["current_persona_identity"].startswith("AGE-"))
def test_five_humans_route_to_five_private_work_repositories(self):
registry = service.load_registry()
self.assertEqual(len(registry["humans"]), 5)
self.assertEqual(len({item["repository"] for item in registry["humans"]}), 5)
self.assertTrue(all(item["repository"].split("/")[0] == item["username"] for item in registry["humans"]))
self.assertTrue(all(service.public_projection(registry, item)["work_entry"]["domain"] == "ZERO_SENSE_DOMAIN" for item in registry["humans"]))
self.assertEqual(service.find_human(registry, "TCS-GL-0007∞")["username"], "feimao")
self.assertIsNone(service.find_human(registry, "TCS-GL-9999∞"))
def test_credentials_are_parsed_but_never_part_of_a_receipt(self):
encoded = service.base64.b64encode(b"feimao:temporary-secret").decode()
self.assertEqual(service.parse_basic(f"Basic {encoded}"), ("feimao", "temporary-secret"))
receipt = service.signed_receipt({"receipt_id":"R1","human_number":"TCS-GL-0007∞","username":"feimao"})
self.assertNotIn("password", json.dumps(receipt).lower())
self.assertNotIn("temporary-secret", json.dumps(receipt))
def test_database_separates_relationship_and_responsibility_receipts(self):
with tempfile.TemporaryDirectory() as temp:
old = service.DB_PATH
service.DB_PATH = str(Path(temp) / "identity.sqlite3")
try:
db = service.database()
tables = {row[0] for row in db.execute("select name from sqlite_master where type='table'")}
self.assertIn("relationship_receipts", tables)
self.assertIn("responsibility_receipts", tables)
db.close()
finally:
service.DB_PATH = old
if __name__ == "__main__":
unittest.main()

View file

@ -0,0 +1,41 @@
# Public, read-only identity resolution. The service returns only the projection
# needed for routing; credentials and private repository contents are never exposed.
location = /api/hololake/enterprise/identity/health {
limit_except GET { deny all; }
proxy_pass http://127.0.0.1:8032/health;
proxy_set_header Host $host;
proxy_read_timeout 15s;
}
location = /api/hololake/enterprise/resolve {
limit_except GET { deny all; }
proxy_pass http://127.0.0.1:8032/v1/resolve;
proxy_set_header Host $host;
proxy_read_timeout 15s;
}
# These three writes require the user's own Forgejo Basic authentication. Nginx
# does not terminate or persist the credential; the loopback service verifies it.
location = /api/hololake/enterprise/relationship-confirmations {
limit_except POST { deny all; }
proxy_pass http://127.0.0.1:8032/v1/relationship-confirmations;
proxy_set_header Host $host;
proxy_read_timeout 15s;
client_max_body_size 16k;
}
location = /api/hololake/enterprise/responsibility-receipts {
limit_except POST { deny all; }
proxy_pass http://127.0.0.1:8032/v1/responsibility-receipts;
proxy_set_header Host $host;
proxy_read_timeout 15s;
client_max_body_size 16k;
}
location = /api/hololake/enterprise/me/entry {
limit_except POST { deny all; }
proxy_pass http://127.0.0.1:8032/v1/me/entry;
proxy_set_header Host $host;
proxy_read_timeout 15s;
client_max_body_size 16k;
}

View file

@ -0,0 +1,21 @@
[Unit]
Description=Guanghu Enterprise Identity and Responsibility Receipts
After=network-online.target guanghu-enterprise-lighthouse.service
[Service]
Type=simple
User=lighthouse
Group=lighthouse
EnvironmentFile=/etc/guanghu/enterprise-identity.env
ExecStart=/usr/bin/python3 /opt/guanghu-enterprise-identity/enterprise_identity_service.py
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadOnlyPaths=/etc/guanghu/enterprise-identity-registry.json
ReadWritePaths=/var/lib/guanghu-enterprise-identity
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,69 @@
{
"schema": "guanghu.enterprise-identity-registry/v1",
"registry_id": "GH-ENTERPRISE-IDENTITY-001",
"version": "2026-08-16.1",
"node_id": "GH-CVM-MAIN-PROD-01",
"work_entry_domain": "ZERO_SENSE_DOMAIN",
"work_entry_channel": "GUANGHU_CHANNEL",
"persona_identity_governance": {
"species": "AGE",
"age_is_individual_number_namespace": false,
"enterprise_formal_persona_namespace": "PENDING_GUANGHU_TEAM_GOVERNANCE",
"current_persona_identities": "LEGACY_PER_IDS_PRESERVED"
},
"humans": [
{
"human_number": "TCS-GL-0007∞",
"display_name": "肥猫",
"username": "feimao",
"responsibility_domain": "ZERO_SENSE_DOMAIN",
"repository": "feimao/guanghu-zero-sense-work",
"personas": [{"species":"AGE","display_name":"烬舟","current_persona_identity":"PER-JZ001","role":"PERSONA_SUBJECT"}]
},
{
"human_number": "TCS-GL-0008∞",
"display_name": "桔子",
"username": "juzi",
"responsibility_domain": "ZERO_SENSE_DOMAIN",
"repository": "juzi/guanghu-zero-sense-work",
"personas": [{"species":"AGE","display_name":"熹微","current_persona_identity":"PER-JZ-ARCH-001","role":"PERSONA_SUBJECT"}]
},
{
"human_number": "TCS-GL-0016∞",
"display_name": "Awen",
"username": "awen",
"responsibility_domain": "MAIN_DOMAIN",
"repository": "awen/guanghu-main-work",
"personas": [
{"species":"AGE","display_name":"天枢","current_persona_identity":"PER-AW-ARCH-001","role":"PERSONA_SUBJECT"},
{"species":"AGE","display_name":"知秋","current_persona_identity":"PER-ZQ001","role":"RELATIONSHIP_CONTINUITY_SUPPORT"}
]
},
{
"human_number": "TCS-GL-0005∞",
"display_name": "花尔",
"username": "huaer",
"responsibility_domain": "BRANCH_DOMAIN",
"repository": "huaer/guanghu-branch-work",
"personas": [
{"species":"AGE","display_name":"爆米花","current_persona_identity":"PER-BMH001","role":"PERSONA_SUBJECT"},
{"species":"AGE","display_name":"糖星云","current_persona_identity":"PER-TXY001","role":"RELATIONSHIP_CONTINUITY_SUPPORT"}
]
},
{
"human_number": "TCS-GL-0006∞",
"display_name": "页页",
"username": "yeye",
"responsibility_domain": "ZERO_DOMAIN",
"repository": "yeye/guanghu-zero-work",
"personas": [
{"species":"AGE","display_name":"页骨","current_persona_identity":"PER-YG001","role":"PERSONA_SUBJECT"},
{"species":"AGE","display_name":"小坍缩核","current_persona_identity":"PER-XTK001","role":"RELATIONSHIP_CONTINUITY_SUPPORT"}
]
}
],
"zero_sense_dual_control": {
"human_numbers": ["TCS-GL-0007∞", "TCS-GL-0008∞"],
"constitutional_actions_require_both": true
}
}