"""Authorized fixed-source collection; password lives only in this process's memory.""" from __future__ import annotations import argparse import getpass import importlib.util import json import logging import socket import sys from pathlib import Path def main() -> None: parser = argparse.ArgumentParser() parser.add_argument("--username", required=True) parser.add_argument("--source-ip", required=True) args = parser.parse_args() password = getpass.getpass("SSH password (not stored): ") logging.disable(logging.CRITICAL) import paramiko original_client = paramiko.SSHClient class DirectLanClient(original_client): def connect(self, hostname, port=22, **kwargs): if hostname != "192.168.110.111" or port != 22: raise ValueError("Unexpected SSH destination") direct = socket.create_connection((hostname, port), timeout=6, source_address=(args.source_ip, 0)) try: return super().connect(hostname, port=port, sock=direct, **kwargs) except Exception: direct.close() raise paramiko.SSHClient = DirectLanClient root = Path(__file__).resolve().parents[1] destination = root / "artifacts/ai_full_verification_20261027/dify_current_source" destination.mkdir(parents=True, exist_ok=True) original = root / "app/artifacts/ai_concurrency/r35_root_source_acquisition" print("AUTH_READY_FIXED_READONLY_ACTIONS", flush=True) for line in sys.stdin: action = line.strip() if action == "quit": break operations = {"inspect", "stage", "imports", "build", "deploy", "rollback", "installed", "health", "logs-safe", "diagnose-imports", "prepare-deploy", "deployment-status"} if action not in {"collect", "dependencies"} | operations: print('{"ok":false,"error_code":"UNKNOWN_ACTION"}', flush=True) continue module_name = "collect_sources" if action == "collect" else "collect_dependencies" try: if action in operations: operation_module = "private_dify_ops_actions_20261027.py" if action == "diagnose-imports": operation_module = "private_dify_ops_actions_v2_20261027.py" elif action in {"prepare-deploy", "deploy", "rollback", "deployment-status"}: operation_module = "private_dify_rollout_actions_20261027.py" spec = importlib.util.spec_from_file_location("private_dify_ops_actions", root / "artifacts" / operation_module) module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module spec.loader.exec_module(module) client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.RejectPolicy()) try: client.connect("192.168.110.111", username=args.username, password=password, look_for_keys=False, allow_agent=False, timeout=6, auth_timeout=6, banner_timeout=6) summary = module.run_action(client, action, root) finally: client.close() print(json.dumps({"ok": True, "action": action, "summary": summary}), flush=True) continue spec = importlib.util.spec_from_file_location("private_dify_" + module_name, original / (module_name + ".py")) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) module.HERE = destination # BASE keeps the read-only historical inventory. Output is NEW. summary = module.collect(username=args.username, password=password) print(json.dumps({"ok": True, "action": action, "summary": summary}), flush=True) except Exception as exc: # Do not print remote stderr, credentials, commands, or source bodies. print(json.dumps({"ok": False, "action": action, "error_type": type(exc).__name__}), flush=True) password = "" if __name__ == "__main__": main()