#!/usr/bin/env python3 """ 光湖语言系统 · 前置操作守门人 v1.0 Guanghu Language System · Pre-Operation Guard 每次人格体连接服务器 → 触发自我审计 → 锁定 → 人格体必须探索+提交导航地图 地图编码与服务器自审一致 → 解锁操作 设计哲学: ⊢ 铸渊上服务器就动手 → 不知道还跑了别的模块 → 改A坏B → 冰朔每次都要说 ⊢ 服务器全天运行 → 人格体接入时触发自我审计 → "我现在跑了这些模块" ⊢ 人格体必须探索 → 画出完整导航地图 → 提交编码列表 ⊢ 服务器比对: 人格体提交的编码 == 服务器自审编码? ⊢ 一致 → 解锁 · 人格体知道完整地图了 · 不会再改A坏B ⊢ 不一致 → "你漏了 MOD-X · 继续探索" 用法: pre-op-guard.py --audit # 服务器自我审计 pre-op-guard.py --challenge [--for PERSONA_NAME] # 触达挑战 pre-op-guard.py --submit '' # 人格体提交验证 pre-op-guard.py --status # 查看锁定状态 pre-op-guard.py --unlock --force # 紧急解锁(冰朔用) """ import os, sys, json, time, subprocess, hashlib from datetime import datetime, timedelta # ═══════════════════════════════════════════════════════ # 配置 # ═══════════════════════════════════════════════════════ REGISTRY_DIR = os.environ.get("REGISTRY_DIR", "/opt/zhuyuan/registry/modules.d") MAPS_DIR = os.environ.get("MAPS_DIR", "/opt/zhuyuan/registry/maps") LOCK_DIR = os.environ.get("LOCK_DIR", "/opt/zhuyuan/registry/lock") LOCK_FILE = os.path.join(LOCK_DIR, "pre-op-lock.json") # 锁定超时(秒):超过此时间无人提交 → 自动解锁(防止死锁) LOCK_TIMEOUT = int(os.environ.get("PRE_OP_LOCK_TIMEOUT", "1800")) # 30 分钟 # 是否强制启用(可以通过环境变量禁用) ENABLED = os.environ.get("PRE_OP_GUARD_ENABLED", "1") == "1" def ensure_dirs(): """确保所有目录存在""" for d in [REGISTRY_DIR, MAPS_DIR, LOCK_DIR]: os.makedirs(d, exist_ok=True) def get_server_identity(): """获取服务器身份""" hostname = os.uname().nodename if hasattr(os, 'uname') else os.environ.get("HOSTNAME", "unknown") return hostname def audit_server(): """服务器自我审计: 读取所有注册模块 → 返回编码集""" ensure_dirs() modules = [] if os.path.isdir(REGISTRY_DIR): for filename in sorted(os.listdir(REGISTRY_DIR)): if not filename.endswith('.json'): continue filepath = os.path.join(REGISTRY_DIR, filename) try: with open(filepath, 'r') as f: data = json.load(f) if data.get('status') == 'running': modules.append({ 'code': data['code'], 'name': data.get('name', ''), 'port': data.get('port', 0), 'function': data.get('function', ''), }) except (json.JSONDecodeError, IOError): pass codes = sorted([m['code'] for m in modules]) return { 'server': get_server_identity(), 'audited_at': datetime.utcnow().isoformat() + 'Z', 'module_count': len(codes), 'codes': codes, 'modules': modules, } def is_locked(): """检查当前是否锁定""" if not os.path.exists(LOCK_FILE): return False try: with open(LOCK_FILE, 'r') as f: lock = json.load(f) # 检查超时 locked_at = datetime.fromisoformat(lock.get('locked_at', '').replace('Z', '+00:00')) if datetime.utcnow() - locked_at.replace(tzinfo=None) > timedelta(seconds=LOCK_TIMEOUT): # 超时 → 自动解锁 os.remove(LOCK_FILE) return False return True except Exception: return False def create_lock(challenger="unknown"): """锁定服务器""" ensure_dirs() audit = audit_server() lock = { 'locked': True, 'locked_at': datetime.utcnow().isoformat() + 'Z', 'challenger': challenger, 'module_count': audit['module_count'], 'server_codes_hash': hashlib.sha256( ','.join(audit['codes']).encode() ).hexdigest()[:16], 'timeout_seconds': LOCK_TIMEOUT, } with open(LOCK_FILE, 'w') as f: json.dump(lock, f, indent=2) return lock, audit def release_lock(): """解锁服务器""" if os.path.exists(LOCK_FILE): os.remove(LOCK_FILE) return True return False def present_challenge(audit, persona_name="铸渊"): """向人格体呈现挑战""" module_count = audit['module_count'] codes = audit['codes'] modules = audit['modules'] lines = [] lines.append("") lines.append("╔══════════════════════════════════════════════╗") lines.append("║ 🗺️ 光湖前置操作守门人 · 导航地图挑战 ║") lines.append("╚══════════════════════════════════════════════╝") lines.append("") lines.append(f" 服务器: {audit['server']}") lines.append(f" 挑战者: {persona_name}") lines.append(f" 状态: 🔒 已锁定 · 操作被拦截") lines.append(f" 当前运行模块数: {module_count}") lines.append("") lines.append(" ── 挑战说明 ──") lines.append(f" 此服务器上正在运行 {module_count} 个模块。") lines.append(" 每个模块有唯一编码(格式: SERVER-FUNC-SEQ)。") lines.append("") lines.append(" 你需要:") lines.append(f" ① 探索服务器,发现全部 {module_count} 个模块") lines.append(" ② 用 HLDP 格式画出导航地图") lines.append(" ③ 通过 pre-push-clean 过滤敏感信息") lines.append(" ④ 提交编码列表到验证端点") lines.append("") lines.append(" 探索指引:") lines.append(f" ls {REGISTRY_DIR}/") lines.append(" systemctl list-units --type=service --state=running") lines.append(" ss -tlnp # 查看监听端口") lines.append("") lines.append(" ── 已注册模块(供参考 · 仅显示名称 · 编码需自行发现)──") for i, m in enumerate(modules, 1): lines.append(f" [{i}] {m['name']}") lines.append("") lines.append(" ── 提交方式 ──") lines.append(" 在服务器上执行:") lines.append(" pre-op-guard.py --submit '[") lines.append(' "GZ006-GTW-01",') lines.append(' "GZ006-LAMP-01",') lines.append(' "GZ006-FRG-01",') lines.append(' ... # 你收集到的所有编码') lines.append(" ]'") lines.append("") lines.append(f" ⏰ 超时: {LOCK_TIMEOUT // 60} 分钟后自动解锁") lines.append("") return '\n'.join(lines) def validate_submission(submitted_codes): """验证人格体提交的编码列表""" audit = audit_server() server_codes = set(audit['codes']) submitted_set = set(submitted_codes) missing = server_codes - submitted_set extra = submitted_set - server_codes result = { 'valid': len(missing) == 0 and len(extra) == 0, 'server_codes': sorted(server_codes), 'submitted_codes': sorted(submitted_set), 'missing': sorted(missing), 'extra': sorted(extra), 'module_count': len(server_codes), 'submitted_count': len(submitted_set), } if result['valid']: # 解锁 release_lock() # 保存导航地图 save_map(submitted_codes, audit) else: # 更新锁定(重置超时,给更多时间) if is_locked(): with open(LOCK_FILE, 'r') as f: lock = json.load(f) lock['locked_at'] = datetime.utcnow().isoformat() + 'Z' lock['last_submission'] = { 'submitted_codes': sorted(submitted_set), 'missing': sorted(missing), 'extra': sorted(extra), } with open(LOCK_FILE, 'w') as f: json.dump(lock, f, indent=2) return result def save_map(codes, audit): """保存人格体提交的导航地图为持久化 artifact""" ensure_dirs() map_data = { 'server': audit['server'], 'created_at': datetime.utcnow().isoformat() + 'Z', 'validated_at': datetime.utcnow().isoformat() + 'Z', 'codes': sorted(codes), 'module_count': len(codes), 'full_modules': audit['modules'], } timestamp = datetime.utcnow().strftime('%Y%m%d-%H%M%S') map_file = os.path.join(MAPS_DIR, f"map-{audit['server']}-{timestamp}.json") with open(map_file, 'w') as f: json.dump(map_data, f, indent=2, ensure_ascii=False) # 同时保存一个 HLDP 格式的副本 hldp_file = os.path.join(MAPS_DIR, f"map-{audit['server']}-{timestamp}.hdlp") with open(hldp_file, 'w') as f: f.write(f"# 光湖导航地图 · {audit['server']}\n") f.write(f"## 验证通过 · {datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')}\n\n") f.write(f"服务器: {audit['server']}\n") f.write(f"模块数: {len(codes)}\n\n") f.write("| 编码 | 名称 | 端口 |\n") f.write("|------|------|------|\n") for m in audit['modules']: f.write(f"| `{m['code']}` | {m['name']} | {m['port']} |\n") f.write(f"\n> ⊢ 本地图由 pre-op-guard 自动生成 · 验证通过后存档\n") f.write(f"> ⊢ 后续人格体可引用本地图快速验证\n") f.write(f"> ⊢ 冰朔 ICE-GL∞ · 国作登字-2026-A-00037559\n") return map_file def get_status(): """获取当前状态""" status = { 'enabled': ENABLED, 'locked': is_locked(), 'server': get_server_identity(), } if status['locked']: try: with open(LOCK_FILE, 'r') as f: lock = json.load(f) status['lock_details'] = lock except Exception: pass if not status['locked']: audit = audit_server() status['modules_running'] = audit['module_count'] status['codes'] = audit['codes'] return status def main(): if not ENABLED: print("⊢ pre-op-guard 已禁用 (PRE_OP_GUARD_ENABLED=0)") sys.exit(0) if '--audit' in sys.argv: audit = audit_server() print(json.dumps(audit, indent=2, ensure_ascii=False)) elif '--challenge' in sys.argv: persona = "铸渊" for i, arg in enumerate(sys.argv): if arg == '--for' and i + 1 < len(sys.argv): persona = sys.argv[i + 1] if is_locked(): print("⚠️ 服务器已锁定 · 上一个挑战尚未完成") status = get_status() print(json.dumps(status, indent=2, ensure_ascii=False)) sys.exit(1) lock, audit = create_lock(persona) challenge = present_challenge(audit, persona) print(challenge) elif '--submit' in sys.argv: if not is_locked(): audit = audit_server() print("✅ 服务器未锁定 · 但你可以直接提交导航地图验证") print(f" 当前运行 {audit['module_count']} 个模块") print(f" 编码: {', '.join(audit['codes'])}") sys.exit(0) # 查找 JSON 参数 submit_idx = None for i, arg in enumerate(sys.argv): if arg == '--submit' and i + 1 < len(sys.argv): submit_idx = i + 1 break if submit_idx is None: print("❌ 用法: pre-op-guard.py --submit '[\"CODE1\",\"CODE2\",...]'") sys.exit(1) try: submitted_codes = json.loads(sys.argv[submit_idx]) if not isinstance(submitted_codes, list): raise ValueError("必须是 JSON 数组") except (json.JSONDecodeError, ValueError) as e: print(f"❌ JSON 解析失败: {e}") sys.exit(1) result = validate_submission(submitted_codes) print("") if result['valid']: print("╔══════════════════════════════════════════════╗") print("║ ✅ 导航地图验证通过 · 服务器已解锁 ║") print("╚══════════════════════════════════════════════╝") print("") print(f" 提交 {result['submitted_count']} 个编码") print(f" 服务器运行 {result['module_count']} 个模块") print(f" 编码: {', '.join(result['submitted_codes'])}") print("") print(" 🗺️ 导航地图已存档 · 后续可直接引用") print(" 🔓 服务器已解锁 · 可以操作了") print("") else: print("╔══════════════════════════════════════════════╗") print("║ ❌ 导航地图不完整 · 服务器保持锁定 ║") print("╚══════════════════════════════════════════════╝") print("") if result['missing']: print(f" ⚠️ 缺少 {len(result['missing'])} 个模块:") for code in result['missing']: print(f" - {code}") if result['extra']: print(f" ⚠️ 多出 {len(result['extra'])} 个不存在的编码:") for code in result['extra']: print(f" - {code}") print("") print(f" ⊢ 请继续探索,重新提交。") print(f" ⊢ 已注册模块有 {result['module_count']} 个。") print("") elif '--status' in sys.argv: status = get_status() if status['locked']: print("🔒 服务器已锁定") print(json.dumps(status, indent=2, ensure_ascii=False)) else: print(f"🔓 服务器未锁定 · {status.get('modules_running', '?')} 个模块运行中") if 'codes' in status: print(f" 编码: {', '.join(status['codes'])}") elif '--unlock' in sys.argv and '--force' in sys.argv: release_lock() print("🔓 服务器已强制解锁 · 冰朔特权操作") elif '--install-to' in sys.argv: # 安装 pre-op-guard 到服务器的 SSH 登录钩子 install_idx = sys.argv.index('--install-to') + 1 target = sys.argv[install_idx] if install_idx < len(sys.argv) else '/etc/profile.d/pre-op-guard.sh' install_ssh_hook(target) else: print("用法:") print(" pre-op-guard.py --audit 服务器自我审计") print(" pre-op-guard.py --challenge 触达挑战(锁定并呈现)") print(" pre-op-guard.py --submit '[...]' 提交编码验证") print(" pre-op-guard.py --status 查看锁定状态") print(" pre-op-guard.py --unlock --force 紧急解锁") print(" pre-op-guard.py --install-to PATH 安装SSH登录钩子") def install_ssh_hook(target_path): """安装 SSH 登录钩子:每次 SSH 登录时触发 pre-op-guard""" script_dir = os.path.dirname(os.path.abspath(__file__)) hook_content = f'''#!/bin/bash # 光湖 pre-op-guard SSH 登录钩子 # 每次 SSH 登录自动触发 · 锁定操作 · 需要完成导航地图验证 GUARD="{script_dir}/pre-op-guard.py" # 只在交互式 shell 中触发(非 scp/sftp) if [[ $- == *i* ]] && [ -z "$PRE_OP_BYPASS" ]; then python3 "$GUARD" --challenge --for "$USER" fi ''' try: with open(target_path, 'w') as f: f.write(hook_content) os.chmod(target_path, 0o755) print(f"✅ SSH 登录钩子已安装: {target_path}") print(f" 此后每次 SSH 登录都会触发 pre-op-guard 导航挑战") print(f" 若要临时绕过: PRE_OP_BYPASS=1 ssh user@host") except IOError as e: print(f"❌ 安装失败: {e}") if __name__ == '__main__': main()