diff --git a/.understand-anything/fingerprints.json b/.understand-anything/fingerprints.json new file mode 100644 index 0000000..8292bfc --- /dev/null +++ b/.understand-anything/fingerprints.json @@ -0,0 +1,733 @@ +{ + "version": "1.0.0", + "gitCommitHash": "042c4d655090e0ee334208511ec63b6d909d4354", + "generatedAt": "2026-06-23T06:34:02.856Z", + "files": { + ".agents/skills/lemana-vpn-operations/SKILL.md": { + "filePath": ".agents/skills/lemana-vpn-operations/SKILL.md", + "contentHash": "27cec75695c23c1dc759d61b5b6250306f3b494688aabc794014711b59aa89ab", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 71, + "hasStructuralAnalysis": true + }, + ".agents/skills/lemana-vpn-sso-autofill/SKILL.md": { + "filePath": ".agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "contentHash": "e597d0e67861787f5c444c74376bdd514614765dbe27dd62b62f7e61925a643c", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 81, + "hasStructuralAnalysis": true + }, + ".agents/skills/lemana-vpn-testing/SKILL.md": { + "filePath": ".agents/skills/lemana-vpn-testing/SKILL.md", + "contentHash": "6f4698688ef498f4f1427024a735d7d36cb96a96f36bf8597977fdc28e3ffa13", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 102, + "hasStructuralAnalysis": true + }, + "AGENTS.md": { + "filePath": "AGENTS.md", + "contentHash": "3ccea1ed9dacb6f1173a03d8053c5466fc03aebcadb6dbf4db52814c82bc6a92", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 89, + "hasStructuralAnalysis": true + }, + "app/Package.swift": { + "filePath": "app/Package.swift", + "contentHash": "338b2954b4fde437b35e7b419d7aff8451d91df790429a168d80d19bf5b99f75", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 15, + "hasStructuralAnalysis": false + }, + "app/Sources/LemanaVPN/LemanaVPNApp.swift": { + "filePath": "app/Sources/LemanaVPN/LemanaVPNApp.swift", + "contentHash": "0caddaae55a376d20d023c3e82b525fa2a54002a2730978e22826aad56574474", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 191, + "hasStructuralAnalysis": false + }, + "app/Sources/LemanaVPN/VPNManager.swift": { + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "contentHash": "16b7da9acd2bad9ff71f3c067ae2bd420c3ef11cab4dc6d9c509be2d0a011d67", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 698, + "hasStructuralAnalysis": false + }, + "bin/vpn-lemanapro.sh": { + "filePath": "bin/vpn-lemanapro.sh", + "contentHash": "e1946792a405d2178b197ea11285029ef172a65dd9f9c6b4a8f308e0ac58bbc2", + "functions": [ + { + "name": "_emit", + "params": [], + "exported": false, + "lineCount": 8 + }, + { + "name": "_write_status", + "params": [], + "exported": false, + "lineCount": 4 + }, + { + "name": "_clear_status", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "_prepare_connection_log", + "params": [], + "exported": false, + "lineCount": 8 + }, + { + "name": "_log_connection_line", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "_show_connection_log_tail", + "params": [], + "exported": false, + "lineCount": 5 + }, + { + "name": "_start_connect_progress", + "params": [], + "exported": false, + "lineCount": 9 + }, + { + "name": "_stop_connect_progress", + "params": [], + "exported": false, + "lineCount": 7 + }, + { + "name": "_json_get", + "params": [], + "exported": false, + "lineCount": 4 + }, + { + "name": "_find_webengine_process", + "params": [], + "exported": false, + "lineCount": 7 + }, + { + "name": "_find_authenticator", + "params": [], + "exported": false, + "lineCount": 7 + }, + { + "name": "_module_bool", + "params": [], + "exported": false, + "lineCount": 7 + }, + { + "name": "_patches_active", + "params": [], + "exported": false, + "lineCount": 15 + }, + { + "name": "_keychain_has", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "_module_status_json", + "params": [], + "exported": false, + "lineCount": 40 + }, + { + "name": "_module_human_part", + "params": [], + "exported": false, + "lineCount": 10 + }, + { + "name": "_module_status_human", + "params": [], + "exported": false, + "lineCount": 35 + }, + { + "name": "_check_status", + "params": [], + "exported": false, + "lineCount": 63 + }, + { + "name": "_patch_oc", + "params": [], + "exported": false, + "lineCount": 228 + }, + { + "name": "autoFill", + "params": [], + "exported": false, + "lineCount": 4 + }, + { + "name": "autoFill", + "params": [], + "exported": false, + "lineCount": 10 + }, + { + "name": "_store_keychain", + "params": [], + "exported": false, + "lineCount": 16 + }, + { + "name": "_normalize_totp_secret", + "params": [], + "exported": false, + "lineCount": 27 + }, + { + "name": "_can_prompt", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "_prompt_read", + "params": [], + "exported": false, + "lineCount": 19 + }, + { + "name": "_persist_username", + "params": [], + "exported": false, + "lineCount": 44 + }, + { + "name": "_ensure_username", + "params": [], + "exported": false, + "lineCount": 26 + }, + { + "name": "_configure_keychain", + "params": [], + "exported": false, + "lineCount": 39 + }, + { + "name": "_ensure_keychain_credentials", + "params": [], + "exported": false, + "lineCount": 28 + }, + { + "name": "_bw_cache_session", + "params": [], + "exported": false, + "lineCount": 6 + }, + { + "name": "_bw_unlock", + "params": [], + "exported": false, + "lineCount": 67 + }, + { + "name": "_sync_bitwarden", + "params": [], + "exported": false, + "lineCount": 35 + }, + { + "name": "_sync_credentials", + "params": [], + "exported": false, + "lineCount": 10 + }, + { + "name": "_dns_cleanup", + "params": [], + "exported": false, + "lineCount": 17 + }, + { + "name": "_filter_output", + "params": [], + "exported": false, + "lineCount": 51 + } + ], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 1091, + "hasStructuralAnalysis": true + }, + "docs/goals/manual-first-auth-flow/GOAL.md": { + "filePath": "docs/goals/manual-first-auth-flow/GOAL.md", + "contentHash": "27fc0e7feddd4c77f78f1966ab1e58c3727b4796f8600003e31e81b907b6ebe7", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 14, + "hasStructuralAnalysis": true + }, + "docs/goals/manual-first-auth-flow/PLAN.md": { + "filePath": "docs/goals/manual-first-auth-flow/PLAN.md", + "contentHash": "459cb4b63f0ea0eee13ed6c8dd91d4bae1be7adaf443b2824a93d2217cbe1c58", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 441, + "hasStructuralAnalysis": true + }, + "docs/superpowers/plans/2026-05-24-keychain-totp-provider.md": { + "filePath": "docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "contentHash": "1a5d622b3bb8c6277d5d97effbdd07713975b4595bec236ff8710abde772c5dc", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 936, + "hasStructuralAnalysis": true + }, + "install.sh": { + "filePath": "install.sh", + "contentHash": "d33186be9dc6457ca80886f629995edf21143d091b6902814853424400a1ec6f", + "functions": [ + { + "name": "usage", + "params": [], + "exported": false, + "lineCount": 35 + }, + { + "name": "log", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "color_line", + "params": [], + "exported": false, + "lineCount": 5 + }, + { + "name": "log_step", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "log_info", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "log_detail", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "log_ok", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "log_warn", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "log_skip", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "die", + "params": [], + "exported": false, + "lineCount": 4 + }, + { + "name": "run", + "params": [], + "exported": false, + "lineCount": 11 + }, + { + "name": "need_cmd", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "has_tty", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "interactive_enabled", + "params": [], + "exported": false, + "lineCount": 8 + }, + { + "name": "prompt_printf", + "params": [], + "exported": false, + "lineCount": 7 + }, + { + "name": "prompt_read_answer", + "params": [], + "exported": false, + "lineCount": 7 + }, + { + "name": "yes_no", + "params": [], + "exported": false, + "lineCount": 27 + }, + { + "name": "choose_credential_source_interactive", + "params": [], + "exported": false, + "lineCount": 51 + }, + { + "name": "bool_word", + "params": [], + "exported": false, + "lineCount": 7 + }, + { + "name": "keychain_has", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "zsh_aliases_installed", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "print_detected_state", + "params": [], + "exported": false, + "lineCount": 18 + }, + { + "name": "choose_modules", + "params": [], + "exported": false, + "lineCount": 96 + }, + { + "name": "script_dir", + "params": [], + "exported": false, + "lineCount": 6 + }, + { + "name": "download_file", + "params": [], + "exported": false, + "lineCount": 18 + }, + { + "name": "write_file", + "params": [], + "exported": false, + "lineCount": 9 + }, + { + "name": "install_homebrew_packages", + "params": [], + "exported": false, + "lineCount": 27 + }, + { + "name": "install_openconnect_lite", + "params": [], + "exported": false, + "lineCount": 18 + }, + { + "name": "install_cli", + "params": [], + "exported": false, + "lineCount": 15 + }, + { + "name": "install_config", + "params": [], + "exported": false, + "lineCount": 25 + }, + { + "name": "install_dns_cleanup", + "params": [], + "exported": false, + "lineCount": 14 + }, + { + "name": "install_sudoers", + "params": [], + "exported": false, + "lineCount": 28 + }, + { + "name": "install_touchid_helper", + "params": [], + "exported": false, + "lineCount": 24 + }, + { + "name": "install_menu_bar_app", + "params": [], + "exported": false, + "lineCount": 60 + }, + { + "name": "install_launch_agent", + "params": [], + "exported": false, + "lineCount": 41 + }, + { + "name": "restart_running_menu_bar_app", + "params": [], + "exported": false, + "lineCount": 19 + }, + { + "name": "install_shell_aliases", + "params": [], + "exported": false, + "lineCount": 45 + }, + { + "name": "vpn", + "params": [], + "exported": false, + "lineCount": 1 + }, + { + "name": "maybe_login_bitwarden", + "params": [], + "exported": false, + "lineCount": 22 + }, + { + "name": "main", + "params": [], + "exported": false, + "lineCount": 40 + } + ], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 944, + "hasStructuralAnalysis": true + }, + "libexec/lemana-vpn-dns-cleanup": { + "filePath": "libexec/lemana-vpn-dns-cleanup", + "contentHash": "9338f2615ba4ef133b42b07dcdbc9e54ddf59b301fd1434e81ea3f36bba16dfb", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 24, + "hasStructuralAnalysis": false + }, + "README.md": { + "filePath": "README.md", + "contentHash": "fa2024f70a4eb7556b501ec01f5c74d7981939d20a805bdbb4a534853618560d", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 580, + "hasStructuralAnalysis": true + }, + "templates/openconnect-lite-config.toml": { + "filePath": "templates/openconnect-lite-config.toml", + "contentHash": "e3378bc1f313fd8087886e582f9ec402268649125db4b0320365b5c3f65611b6", + "functions": [], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 33, + "hasStructuralAnalysis": true + }, + "tests/smoke.sh": { + "filePath": "tests/smoke.sh", + "contentHash": "1cf9648a22e831c0693d328edcbc0e5e6561084244a20dfb37d95dd6f7f8f23e", + "functions": [ + { + "name": "autoFill", + "params": [], + "exported": false, + "lineCount": 4 + } + ], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 439, + "hasStructuralAnalysis": true + }, + "uninstall.sh": { + "filePath": "uninstall.sh", + "contentHash": "6ad75a4fbbe52575eb3672a1eac06734e13f4a82d77cba17dfe2aee75b6ecfba", + "functions": [ + { + "name": "usage", + "params": [], + "exported": false, + "lineCount": 18 + }, + { + "name": "log", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "color_line", + "params": [], + "exported": false, + "lineCount": 5 + }, + { + "name": "log_step", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "log_info", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "log_detail", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "log_ok", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "log_warn", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "log_skip", + "params": [], + "exported": false, + "lineCount": 3 + }, + { + "name": "die", + "params": [], + "exported": false, + "lineCount": 4 + }, + { + "name": "run", + "params": [], + "exported": false, + "lineCount": 11 + }, + { + "name": "find_webengine_process", + "params": [], + "exported": false, + "lineCount": 7 + }, + { + "name": "restore_openconnect_lite_patch", + "params": [], + "exported": false, + "lineCount": 21 + }, + { + "name": "remove_zshrc_block", + "params": [], + "exported": false, + "lineCount": 22 + }, + { + "name": "remove_keychain_entries", + "params": [], + "exported": false, + "lineCount": 29 + }, + { + "name": "main", + "params": [], + "exported": false, + "lineCount": 83 + } + ], + "classes": [], + "imports": [], + "exports": [], + "totalLines": 321, + "hasStructuralAnalysis": true + } + } +} \ No newline at end of file diff --git a/.understand-anything/intermediate/assembled-graph.json b/.understand-anything/intermediate/assembled-graph.json index 0b642b5..f3c8aea 100644 --- a/.understand-anything/intermediate/assembled-graph.json +++ b/.understand-anything/intermediate/assembled-graph.json @@ -1566,6 +1566,472 @@ "type": "contains", "direction": "forward", "weight": 1 + }, + { + "source": "document:README.md", + "target": "file:install.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "file:bin/vpn-lemanapro.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "file:uninstall.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "config:templates/openconnect-lite-config.toml", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "file:libexec/lemana-vpn-dns-cleanup", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:AGENTS.md", + "target": "document:.agents/skills/lemana-vpn-operations/SKILL.md", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:AGENTS.md", + "target": "document:.agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:AGENTS.md", + "target": "document:.agents/skills/lemana-vpn-testing/SKILL.md", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-operations/SKILL.md", + "target": "file:install.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-operations/SKILL.md", + "target": "file:bin/vpn-lemanapro.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-operations/SKILL.md", + "target": "file:uninstall.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "target": "file:bin/vpn-lemanapro.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "target": "config:templates/openconnect-lite-config.toml", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-testing/SKILL.md", + "target": "file:tests/smoke.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/goals/manual-first-auth-flow/GOAL.md", + "target": "document:docs/goals/manual-first-auth-flow/PLAN.md", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/goals/manual-first-auth-flow/PLAN.md", + "target": "file:install.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/goals/manual-first-auth-flow/PLAN.md", + "target": "file:bin/vpn-lemanapro.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/goals/manual-first-auth-flow/PLAN.md", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/goals/manual-first-auth-flow/PLAN.md", + "target": "file:tests/smoke.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "target": "file:install.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "target": "file:bin/vpn-lemanapro.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "target": "file:tests/smoke.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "file:install.sh", + "target": "file:bin/vpn-lemanapro.sh", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:uninstall.sh", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "config:templates/openconnect-lite-config.toml", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:libexec/lemana-vpn-dns-cleanup", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:app/Package.swift", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:uninstall.sh", + "target": "file:bin/vpn-lemanapro.sh", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:uninstall.sh", + "target": "file:libexec/lemana-vpn-dns-cleanup", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "file:bin/vpn-lemanapro.sh", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "config:templates/openconnect-lite-config.toml", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "file:libexec/lemana-vpn-dns-cleanup", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:app/Package.swift", + "target": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "type": "configures", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:app/Package.swift", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "configures", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "config:templates/openconnect-lite-config.toml", + "target": "file:bin/vpn-lemanapro.sh", + "type": "configures", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "file:uninstall.sh", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "config:templates/openconnect-lite-config.toml", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + } + ], + "version": "1.0.0", + "project": { + "name": "Lemana VPN", + "languages": [ + "markdown", + "swift", + "shell", + "unknown", + "toml" + ], + "frameworks": [ + "SwiftUI", + "AppKit", + "openconnect-lite", + "Bitwarden CLI", + "macOS Keychain" + ], + "description": "macOS-пакет для корпоративного VPN Lemana: installer, CLI runtime, SSO/autofill через openconnect-lite, DNS cleanup wrapper и Swift menu bar app.", + "analyzedAt": "2026-06-23T06:33:02.614Z", + "gitCommitHash": "042c4d655090e0ee334208511ec63b6d909d4354" + }, + "layers": [ + { + "id": "layer:documentation-and-agent-guidance", + "name": "Документация и agent guidance", + "description": "Пользовательская документация, локальные agent skills и планы, которые описывают ожидаемые операции, safety rules и будущие изменения.", + "nodeIds": [ + "document:README.md", + "document:AGENTS.md", + "document:.agents/skills/lemana-vpn-operations/SKILL.md", + "document:.agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "document:.agents/skills/lemana-vpn-testing/SKILL.md", + "document:docs/goals/manual-first-auth-flow/GOAL.md", + "document:docs/goals/manual-first-auth-flow/PLAN.md", + "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md" + ] + }, + { + "id": "layer:installer-and-uninstaller", + "name": "Installer и uninstall слой", + "description": "Shell scripts, которые устанавливают, обновляют и удаляют локальный VPN пакет, включая dependencies, app bundle, aliases, sudoers и cleanup.", + "nodeIds": [ + "file:install.sh", + "file:uninstall.sh" + ] + }, + { + "id": "layer:runtime-cli-and-system-integration", + "name": "Runtime CLI и системная интеграция", + "description": "Основной CLI, openconnect-lite config и DNS cleanup wrapper, которые управляют SSO, credentials, VPN session status и системной очисткой DNS.", + "nodeIds": [ + "file:bin/vpn-lemanapro.sh", + "config:templates/openconnect-lite-config.toml", + "file:libexec/lemana-vpn-dns-cleanup" + ] + }, + { + "id": "layer:swift-menu-bar-app", + "name": "Swift menu bar app", + "description": "Swift Package и SwiftUI/AppKit код menu bar приложения, которое запускает CLI, показывает статус и предоставляет user-facing actions.", + "nodeIds": [ + "file:app/Package.swift", + "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "file:app/Sources/LemanaVPN/VPNManager.swift" + ] + }, + { + "id": "layer:verification", + "name": "Verification слой", + "description": "Non-live smoke suite, который закрепляет синтаксис, installer/runtime/app wiring и SSO patch/config expectations.", + "nodeIds": [ + "file:tests/smoke.sh" + ] + } + ], + "tour": [ + { + "order": 1, + "title": "Назначение проекта", + "description": "Начните с README и AGENTS, чтобы понять пользовательский контракт, состав пакета и правила безопасной работы с live VPN.", + "nodeIds": [ + "document:README.md", + "document:AGENTS.md" + ], + "languageLesson": "Markdown здесь используется как операционный runbook: таблицы путей, shell blocks и safety sections важнее обычного prose." + }, + { + "order": 2, + "title": "Установка и удаление", + "description": "Разберите installer и uninstaller: они определяют, какие артефакты попадают в систему и как их безопасно откатить.", + "nodeIds": [ + "file:install.sh", + "file:uninstall.sh" + ], + "languageLesson": "Shell strict-mode и idempotent функции помогают повторять установку без ручной чистки состояния." + }, + { + "order": 3, + "title": "Runtime CLI", + "description": "Основной runtime находится в `vpn-lemanapro.sh`: он синхронизирует credentials, применяет patches, запускает SSO и публикует JSON events.", + "nodeIds": [ + "file:bin/vpn-lemanapro.sh", + "config:templates/openconnect-lite-config.toml", + "file:libexec/lemana-vpn-dns-cleanup" + ] + }, + { + "order": 4, + "title": "SSO, credentials и autofill", + "description": "SSO skill и historical plans объясняют, почему runtime разделяет Bitwarden sync, Keychain-only flow, TOTP normalization и manual/full-manual режимы.", + "nodeIds": [ + "document:.agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "file:bin/vpn-lemanapro.sh" + ] + }, + { + "order": 5, + "title": "Menu bar app", + "description": "Swift layer показывает user-facing поверхность: `LemanaVPNApp` строит меню, а `VPNManager` мостит app с CLI JSON events и health checks.", + "nodeIds": [ + "file:app/Package.swift", + "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "file:app/Sources/LemanaVPN/VPNManager.swift" + ], + "languageLesson": "SwiftUI state flow здесь строится вокруг `ObservableObject` и `@Published`: изменения CLI events автоматически обновляют меню." + }, + { + "order": 6, + "title": "Проверка без live VPN", + "description": "Закончите smoke suite и testing skill: они показывают, какие проверки можно делать до любого реального подключения.", + "nodeIds": [ + "file:tests/smoke.sh", + "document:.agents/skills/lemana-vpn-testing/SKILL.md" + ] } ] } \ No newline at end of file diff --git a/.understand-anything/knowledge-graph.json b/.understand-anything/knowledge-graph.json new file mode 100644 index 0000000..f3c8aea --- /dev/null +++ b/.understand-anything/knowledge-graph.json @@ -0,0 +1,2037 @@ +{ + "nodes": [ + { + "id": "document:AGENTS.md", + "type": "document", + "name": "AGENTS.md", + "filePath": "AGENTS.md", + "summary": "Репозиторные правила для агентов: модель системы, live VPN safety, тестовая лестница и контракт финального ответа.", + "tags": [ + "agent-rules", + "documentation", + "safety" + ], + "complexity": "moderate" + }, + { + "id": "document:README.md", + "type": "document", + "name": "README.md", + "filePath": "README.md", + "summary": "Основная пользовательская документация Lemana VPN: установка, credential sources, модули, использование, диагностика и удаление.", + "tags": [ + "documentation", + "overview", + "user-guide" + ], + "complexity": "complex" + }, + { + "id": "file:install.sh", + "type": "file", + "name": "install.sh", + "filePath": "install.sh", + "summary": "Installer wizard для Homebrew/pipx/openconnect-lite, CLI, config, DNS wrapper, sudoers, Touch ID helper, Swift app, launch agent и shell aliases.", + "tags": [ + "installer", + "wizard", + "macos" + ], + "complexity": "complex" + }, + { + "id": "function:install.sh:usage", + "type": "function", + "name": "usage", + "filePath": "install.sh", + "lineRange": [ + 72, + 106 + ], + "summary": "Значимая функция usage в install.sh.", + "tags": [ + "function", + "runtime", + "usage" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:yes_no", + "type": "function", + "name": "yes_no", + "filePath": "install.sh", + "lineRange": [ + 304, + 330 + ], + "summary": "Значимая функция yes_no в install.sh.", + "tags": [ + "function", + "runtime", + "yes-no" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:choose_credential_source_interactive", + "type": "function", + "name": "choose_credential_source_interactive", + "filePath": "install.sh", + "lineRange": [ + 332, + 382 + ], + "summary": "Показывает интерактивный выбор credential source и нормализует ответ пользователя.", + "tags": [ + "function", + "runtime", + "choose-credential-source-interactive" + ], + "complexity": "moderate" + }, + { + "id": "function:install.sh:print_detected_state", + "type": "function", + "name": "print_detected_state", + "filePath": "install.sh", + "lineRange": [ + 400, + 417 + ], + "summary": "Значимая функция print_detected_state в install.sh.", + "tags": [ + "function", + "runtime", + "print-detected-state" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:choose_modules", + "type": "function", + "name": "choose_modules", + "filePath": "install.sh", + "lineRange": [ + 419, + 514 + ], + "summary": "Определяет набор устанавливаемых модулей с учетом интерактивного режима и флагов installer.", + "tags": [ + "function", + "runtime", + "choose-modules" + ], + "complexity": "moderate" + }, + { + "id": "function:install.sh:download_file", + "type": "function", + "name": "download_file", + "filePath": "install.sh", + "lineRange": [ + 523, + 540 + ], + "summary": "Значимая функция download_file в install.sh.", + "tags": [ + "function", + "runtime", + "download-file" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:install_homebrew_packages", + "type": "function", + "name": "install_homebrew_packages", + "filePath": "install.sh", + "lineRange": [ + 552, + 578 + ], + "summary": "Значимая функция install_homebrew_packages в install.sh.", + "tags": [ + "function", + "runtime", + "install-homebrew-packages" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:install_openconnect_lite", + "type": "function", + "name": "install_openconnect_lite", + "filePath": "install.sh", + "lineRange": [ + 580, + 597 + ], + "summary": "Устанавливает или проверяет openconnect-lite runtime, необходимый для SAML SSO.", + "tags": [ + "function", + "runtime", + "install-openconnect-lite" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:install_cli", + "type": "function", + "name": "install_cli", + "filePath": "install.sh", + "lineRange": [ + 599, + 613 + ], + "summary": "Копирует основной CLI и uninstall helper в пользовательский bin.", + "tags": [ + "function", + "runtime", + "install-cli" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:install_config", + "type": "function", + "name": "install_config", + "filePath": "install.sh", + "lineRange": [ + 615, + 639 + ], + "summary": "Устанавливает шаблон openconnect-lite config и сохраняет локальную конфигурацию модулей.", + "tags": [ + "function", + "runtime", + "install-config" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:install_dns_cleanup", + "type": "function", + "name": "install_dns_cleanup", + "filePath": "install.sh", + "lineRange": [ + 641, + 654 + ], + "summary": "Устанавливает root-owned DNS cleanup wrapper для безопасного сброса корпоративных DNS.", + "tags": [ + "function", + "runtime", + "install-dns-cleanup" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:install_sudoers", + "type": "function", + "name": "install_sudoers", + "filePath": "install.sh", + "lineRange": [ + 656, + 683 + ], + "summary": "Пишет ограниченные sudoers правила для openconnect и DNS cleanup wrapper.", + "tags": [ + "function", + "runtime", + "install-sudoers" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:install_touchid_helper", + "type": "function", + "name": "install_touchid_helper", + "filePath": "install.sh", + "lineRange": [ + 685, + 708 + ], + "summary": "Собирает и устанавливает Touch ID helper для Bitwarden master password.", + "tags": [ + "function", + "runtime", + "install-touchid-helper" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:install_menu_bar_app", + "type": "function", + "name": "install_menu_bar_app", + "filePath": "install.sh", + "lineRange": [ + 710, + 769 + ], + "summary": "Собирает release-версию Swift menu bar app и устанавливает LemanaVPN.app.", + "tags": [ + "function", + "runtime", + "install-menu-bar-app" + ], + "complexity": "moderate" + }, + { + "id": "function:install.sh:install_launch_agent", + "type": "function", + "name": "install_launch_agent", + "filePath": "install.sh", + "lineRange": [ + 771, + 811 + ], + "summary": "Создает LaunchAgent для автозапуска menu bar app при логине.", + "tags": [ + "function", + "runtime", + "install-launch-agent" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:restart_running_menu_bar_app", + "type": "function", + "name": "restart_running_menu_bar_app", + "filePath": "install.sh", + "lineRange": [ + 813, + 831 + ], + "summary": "Перезапускает уже открытое menu bar приложение после обновления bundle.", + "tags": [ + "function", + "runtime", + "restart-running-menu-bar-app" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:install_shell_aliases", + "type": "function", + "name": "install_shell_aliases", + "filePath": "install.sh", + "lineRange": [ + 833, + 877 + ], + "summary": "Добавляет idempotent zsh aliases для CLI режимов подключения и диагностики.", + "tags": [ + "function", + "runtime", + "install-shell-aliases" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:maybe_login_bitwarden", + "type": "function", + "name": "maybe_login_bitwarden", + "filePath": "install.sh", + "lineRange": [ + 879, + 900 + ], + "summary": "Проверяет Bitwarden session и при необходимости запускает login/unlock flow.", + "tags": [ + "function", + "runtime", + "maybe-login-bitwarden" + ], + "complexity": "simple" + }, + { + "id": "function:install.sh:main", + "type": "function", + "name": "main", + "filePath": "install.sh", + "lineRange": [ + 902, + 941 + ], + "summary": "Значимая функция main в install.sh.", + "tags": [ + "function", + "runtime", + "main" + ], + "complexity": "simple" + }, + { + "id": "file:uninstall.sh", + "type": "file", + "name": "uninstall.sh", + "filePath": "uninstall.sh", + "summary": "Uninstaller для восстановления runtime patch backups, удаления CLI/app/config/sudoers/aliases и опциональной очистки Keychain/Touch ID state.", + "tags": [ + "uninstaller", + "cleanup", + "macos" + ], + "complexity": "complex" + }, + { + "id": "function:uninstall.sh:usage", + "type": "function", + "name": "usage", + "filePath": "uninstall.sh", + "lineRange": [ + 62, + 79 + ], + "summary": "Значимая функция usage в uninstall.sh.", + "tags": [ + "function", + "runtime", + "usage" + ], + "complexity": "simple" + }, + { + "id": "function:uninstall.sh:restore_openconnect_lite_patch", + "type": "function", + "name": "restore_openconnect_lite_patch", + "filePath": "uninstall.sh", + "lineRange": [ + 161, + 181 + ], + "summary": "Возвращает backup исходника openconnect-lite, если runtime patch был установлен.", + "tags": [ + "function", + "runtime", + "restore-openconnect-lite-patch" + ], + "complexity": "simple" + }, + { + "id": "function:uninstall.sh:remove_zshrc_block", + "type": "function", + "name": "remove_zshrc_block", + "filePath": "uninstall.sh", + "lineRange": [ + 183, + 204 + ], + "summary": "Удаляет idempotent блок Lemana VPN aliases из zshrc.", + "tags": [ + "function", + "runtime", + "remove-zshrc-block" + ], + "complexity": "simple" + }, + { + "id": "function:uninstall.sh:remove_keychain_entries", + "type": "function", + "name": "remove_keychain_entries", + "filePath": "uninstall.sh", + "lineRange": [ + 206, + 234 + ], + "summary": "Опционально удаляет password, TOTP seed и username из macOS Keychain.", + "tags": [ + "function", + "runtime", + "remove-keychain-entries" + ], + "complexity": "simple" + }, + { + "id": "function:uninstall.sh:main", + "type": "function", + "name": "main", + "filePath": "uninstall.sh", + "lineRange": [ + 236, + 318 + ], + "summary": "Значимая функция main в uninstall.sh.", + "tags": [ + "function", + "runtime", + "main" + ], + "complexity": "moderate" + }, + { + "id": "document:.agents/skills/lemana-vpn-operations/SKILL.md", + "type": "document", + "name": "Lemana VPN Operations skill", + "filePath": ".agents/skills/lemana-vpn-operations/SKILL.md", + "summary": "Инструкции для операционных задач: установка, обновление, статусы, безопасные ответы пользователю и live-connection правила.", + "tags": [ + "skill", + "operations", + "documentation" + ], + "complexity": "moderate" + }, + { + "id": "document:.agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "type": "document", + "name": "Lemana VPN SSO skill", + "filePath": ".agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "summary": "Инструкции по Bitwarden, Keychain, TOTP, Keycloak SSO, autofill и runtime-патчам openconnect-lite.", + "tags": [ + "skill", + "sso", + "credentials" + ], + "complexity": "moderate" + }, + { + "id": "document:.agents/skills/lemana-vpn-testing/SKILL.md", + "type": "document", + "name": "Lemana VPN Testing skill", + "filePath": ".agents/skills/lemana-vpn-testing/SKILL.md", + "summary": "Инструкции по non-live проверкам, status checks, live VPN safety и финальному отчету для изменений в репозитории.", + "tags": [ + "skill", + "testing", + "verification" + ], + "complexity": "moderate" + }, + { + "id": "file:app/Package.swift", + "type": "file", + "name": "Package.swift", + "filePath": "app/Package.swift", + "summary": "Swift Package manifest для сборки executable target LemanaVPN под macOS 13+.", + "tags": [ + "swift", + "build-system", + "menu-bar-app" + ], + "complexity": "simple" + }, + { + "id": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "type": "file", + "name": "LemanaVPNApp.swift", + "filePath": "app/Sources/LemanaVPN/LemanaVPNApp.swift", + "summary": "SwiftUI/AppKit menu bar surface: отображает состояние VPN, кнопки подключения, логи и действия пользователя.", + "tags": [ + "swiftui", + "menu-bar", + "ui" + ], + "complexity": "moderate" + }, + { + "id": "class:app/Sources/LemanaVPN/LemanaVPNApp.swift:LemanaVPNApp", + "type": "class", + "name": "LemanaVPNApp", + "filePath": "app/Sources/LemanaVPN/LemanaVPNApp.swift", + "lineRange": [ + 5, + 16 + ], + "summary": "Точка входа SwiftUI menu bar app, связывает VPNManager с MenuBarExtra.", + "tags": [ + "swift", + "type", + "menu-bar-app" + ], + "complexity": "simple" + }, + { + "id": "class:app/Sources/LemanaVPN/LemanaVPNApp.swift:StatusBarLabel", + "type": "class", + "name": "StatusBarLabel", + "filePath": "app/Sources/LemanaVPN/LemanaVPNApp.swift", + "lineRange": [ + 17, + 51 + ], + "summary": "Компактный status bar label с иконкой и оставшимся временем сессии.", + "tags": [ + "swift", + "type", + "menu-bar-app" + ], + "complexity": "simple" + }, + { + "id": "class:app/Sources/LemanaVPN/LemanaVPNApp.swift:VPNMenuView", + "type": "class", + "name": "VPNMenuView", + "filePath": "app/Sources/LemanaVPN/LemanaVPNApp.swift", + "lineRange": [ + 52, + 191 + ], + "summary": "Основной menu UI с командами auto/manual/manual-full connect, disconnect, logs и quit.", + "tags": [ + "swift", + "type", + "menu-bar-app" + ], + "complexity": "moderate" + }, + { + "id": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "file", + "name": "VPNManager.swift", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "summary": "Основной state manager Swift-приложения: запускает CLI в JSON mode, декодирует события, отслеживает health и управляет reconnect/disconnect.", + "tags": [ + "swift", + "state-manager", + "cli-bridge" + ], + "complexity": "complex" + }, + { + "id": "class:app/Sources/LemanaVPN/VPNManager.swift:VPNEvent", + "type": "class", + "name": "VPNEvent", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 4, + 17 + ], + "summary": "Decodable-модель JSON events, которые runtime CLI отправляет в Swift app.", + "tags": [ + "swift", + "type", + "menu-bar-app" + ], + "complexity": "simple" + }, + { + "id": "class:app/Sources/LemanaVPN/VPNManager.swift:VPNStatusResponse", + "type": "class", + "name": "VPNStatusResponse", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 18, + 21 + ], + "summary": "Decodable envelope для ответа `vpn --status --json`.", + "tags": [ + "swift", + "type", + "menu-bar-app" + ], + "complexity": "simple" + }, + { + "id": "class:app/Sources/LemanaVPN/VPNManager.swift:ModuleStatus", + "type": "class", + "name": "ModuleStatus", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 22, + 101 + ], + "summary": "Модель статуса модулей и вычисление summary/systemImage для menu bar app.", + "tags": [ + "swift", + "type", + "menu-bar-app" + ], + "complexity": "moderate" + }, + { + "id": "class:app/Sources/LemanaVPN/VPNManager.swift:VPNState", + "type": "class", + "name": "VPNState", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 102, + 121 + ], + "summary": "Finite state model для disconnected/connecting/connected/reconnecting/error состояний.", + "tags": [ + "swift", + "type", + "menu-bar-app" + ], + "complexity": "simple" + }, + { + "id": "class:app/Sources/LemanaVPN/VPNManager.swift:VPNLaunchMode", + "type": "class", + "name": "VPNLaunchMode", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 122, + 136 + ], + "summary": "Маппинг app launch modes на CLI flags `--auto`, `--manual`, `--manual-full`.", + "tags": [ + "swift", + "type", + "menu-bar-app" + ], + "complexity": "simple" + }, + { + "id": "class:app/Sources/LemanaVPN/VPNManager.swift:VPNManager", + "type": "class", + "name": "VPNManager", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 137, + 698 + ], + "summary": "ObservableObject, который мостит Swift menu bar app с shell CLI, JSON events и health checks.", + "tags": [ + "swift", + "type", + "state-manager" + ], + "complexity": "complex" + }, + { + "id": "function:app/Sources/LemanaVPN/VPNManager.swift:refreshStatus", + "type": "function", + "name": "refreshStatus", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 194, + 248 + ], + "summary": "Запускает CLI status JSON и обновляет module summary в menu bar app.", + "tags": [ + "function", + "runtime", + "refreshStatus" + ], + "complexity": "moderate" + }, + { + "id": "function:app/Sources/LemanaVPN/VPNManager.swift:connect", + "type": "function", + "name": "connect", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 249, + 326 + ], + "summary": "Запускает CLI в JSON mode с выбранным режимом подключения и подписывается на stdout/stderr.", + "tags": [ + "function", + "runtime", + "connect" + ], + "complexity": "moderate" + }, + { + "id": "function:app/Sources/LemanaVPN/VPNManager.swift:disconnect", + "type": "function", + "name": "disconnect", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 327, + 349 + ], + "summary": "Отправляет SIGINT текущему CLI process и останавливает reconnect state.", + "tags": [ + "function", + "runtime", + "disconnect" + ], + "complexity": "simple" + }, + { + "id": "function:app/Sources/LemanaVPN/VPNManager.swift:parseEvent", + "type": "function", + "name": "parseEvent", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 350, + 448 + ], + "summary": "Декодирует JSON events из CLI и переводит их в Swift state updates.", + "tags": [ + "function", + "runtime", + "parseEvent" + ], + "complexity": "moderate" + }, + { + "id": "function:app/Sources/LemanaVPN/VPNManager.swift:handleTermination", + "type": "function", + "name": "handleTermination", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 449, + 576 + ], + "summary": "Обрабатывает завершение CLI process и решает, нужен ли автоматический reconnect.", + "tags": [ + "function", + "runtime", + "handleTermination" + ], + "complexity": "moderate" + }, + { + "id": "function:app/Sources/LemanaVPN/VPNManager.swift:startHealthCheck", + "type": "function", + "name": "startHealthCheck", + "filePath": "app/Sources/LemanaVPN/VPNManager.swift", + "lineRange": [ + 577, + 666 + ], + "summary": "Периодически проверяет tunnel health и запускает reconnect при повторных failures.", + "tags": [ + "function", + "runtime", + "startHealthCheck" + ], + "complexity": "moderate" + }, + { + "id": "file:bin/vpn-lemanapro.sh", + "type": "file", + "name": "vpn-lemanapro.sh", + "filePath": "bin/vpn-lemanapro.sh", + "summary": "Главный runtime CLI: status JSON, sync credentials, Keychain/TOTP, runtime patches, SSO запуск, reconnect loop, DNS cleanup и фильтрация openconnect-lite output.", + "tags": [ + "cli", + "runtime", + "sso" + ], + "complexity": "complex" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_module_bool", + "type": "function", + "name": "_module_bool", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 197, + 203 + ], + "summary": "Значимая функция _module_bool в bin/vpn-lemanapro.sh.", + "tags": [ + "function", + "runtime", + "module-bool" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_patches_active", + "type": "function", + "name": "_patches_active", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 205, + 219 + ], + "summary": "Значимая функция _patches_active в bin/vpn-lemanapro.sh.", + "tags": [ + "function", + "runtime", + "patches-active" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_module_status_json", + "type": "function", + "name": "_module_status_json", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 225, + 264 + ], + "summary": "Собирает машинно-читаемый JSON со статусом модулей, credentials, app, DNS и patches.", + "tags": [ + "function", + "runtime", + "module-status-json" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_module_human_part", + "type": "function", + "name": "_module_human_part", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 266, + 275 + ], + "summary": "Значимая функция _module_human_part в bin/vpn-lemanapro.sh.", + "tags": [ + "function", + "runtime", + "module-human-part" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_module_status_human", + "type": "function", + "name": "_module_status_human", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 277, + 311 + ], + "summary": "Печатает человекочитаемую строку статуса модулей перед подключением.", + "tags": [ + "function", + "runtime", + "module-status-human" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_check_status", + "type": "function", + "name": "_check_status", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 313, + 375 + ], + "summary": "Проверяет PID/status file, running process, DNS target и возвращает disconnected/connected JSON.", + "tags": [ + "function", + "runtime", + "check-status" + ], + "complexity": "moderate" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_patch_oc", + "type": "function", + "name": "_patch_oc", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 377, + 604 + ], + "summary": "Применяет runtime patches к openconnect-lite для Keycloak autofill/manual/debug сценариев.", + "tags": [ + "function", + "runtime", + "patch-oc" + ], + "complexity": "complex" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_normalize_totp_secret", + "type": "function", + "name": "_normalize_totp_secret", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 623, + 649 + ], + "summary": "Нормализует TOTP secret из raw secret или otpauth URI перед сохранением.", + "tags": [ + "function", + "runtime", + "normalize-totp-secret" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_persist_username", + "type": "function", + "name": "_persist_username", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 675, + 718 + ], + "summary": "Значимая функция _persist_username в bin/vpn-lemanapro.sh.", + "tags": [ + "function", + "runtime", + "persist-username" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_ensure_username", + "type": "function", + "name": "_ensure_username", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 720, + 745 + ], + "summary": "Значимая функция _ensure_username в bin/vpn-lemanapro.sh.", + "tags": [ + "function", + "runtime", + "ensure-username" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_configure_keychain", + "type": "function", + "name": "_configure_keychain", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 747, + 785 + ], + "summary": "Интерактивно сохраняет LDAP password и TOTP seed в macOS Keychain.", + "tags": [ + "function", + "runtime", + "configure-keychain" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_ensure_keychain_credentials", + "type": "function", + "name": "_ensure_keychain_credentials", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 787, + 814 + ], + "summary": "Проверяет наличие обязательных Keychain credentials перед auto/manual подключением.", + "tags": [ + "function", + "runtime", + "ensure-keychain-credentials" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_bw_unlock", + "type": "function", + "name": "_bw_unlock", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 823, + 889 + ], + "summary": "Открывает Bitwarden session с учетом Touch ID helper и fallback prompts.", + "tags": [ + "function", + "runtime", + "bw-unlock" + ], + "complexity": "moderate" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_sync_bitwarden", + "type": "function", + "name": "_sync_bitwarden", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 891, + 925 + ], + "summary": "Синхронизирует LDAP password и TOTP seed из Bitwarden в macOS Keychain.", + "tags": [ + "function", + "runtime", + "sync-bitwarden" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_sync_credentials", + "type": "function", + "name": "_sync_credentials", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 927, + 936 + ], + "summary": "Выбирает credential source и запускает соответствующий sync/preflight путь.", + "tags": [ + "function", + "runtime", + "sync-credentials" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_dns_cleanup", + "type": "function", + "name": "_dns_cleanup", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 938, + 954 + ], + "summary": "Вызывает narrow sudo wrapper для очистки VPN DNS при завершении сессии.", + "tags": [ + "function", + "runtime", + "dns-cleanup" + ], + "complexity": "simple" + }, + { + "id": "function:bin/vpn-lemanapro.sh:_filter_output", + "type": "function", + "name": "_filter_output", + "filePath": "bin/vpn-lemanapro.sh", + "lineRange": [ + 956, + 1006 + ], + "summary": "Фильтрует поток openconnect-lite, извлекает IP/expiry, пишет status JSON и события для app.", + "tags": [ + "function", + "runtime", + "filter-output" + ], + "complexity": "moderate" + }, + { + "id": "document:docs/goals/manual-first-auth-flow/GOAL.md", + "type": "document", + "name": "Manual-first auth goal", + "filePath": "docs/goals/manual-first-auth-flow/GOAL.md", + "summary": "Краткое описание цели manual-first authentication flow и ожидаемого пользовательского результата.", + "tags": [ + "goal", + "auth-flow", + "planning" + ], + "complexity": "simple" + }, + { + "id": "document:docs/goals/manual-first-auth-flow/PLAN.md", + "type": "document", + "name": "Manual-first auth plan", + "filePath": "docs/goals/manual-first-auth-flow/PLAN.md", + "summary": "Подробный план изменения installer UX, CLI auth profiles, Swift menu-bar surface и smoke coverage для manual-first сценария.", + "tags": [ + "plan", + "auth-flow", + "implementation" + ], + "complexity": "complex" + }, + { + "id": "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "type": "document", + "name": "Keychain TOTP provider plan", + "filePath": "docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "summary": "Исторический implementation plan для разделения credential sources, нормализации TOTP и расширения smoke-проверок.", + "tags": [ + "plan", + "keychain", + "totp" + ], + "complexity": "complex" + }, + { + "id": "file:libexec/lemana-vpn-dns-cleanup", + "type": "file", + "name": "lemana-vpn-dns-cleanup", + "filePath": "libexec/lemana-vpn-dns-cleanup", + "summary": "Узкий root-owned wrapper, который сбрасывает только корпоративные DNS и обновляет macOS resolver cache.", + "tags": [ + "dns", + "sudo-wrapper", + "cleanup" + ], + "complexity": "simple" + }, + { + "id": "config:templates/openconnect-lite-config.toml", + "type": "config", + "name": "openconnect-lite-config.toml", + "filePath": "templates/openconnect-lite-config.toml", + "summary": "Шаблон профиля openconnect-lite: gateway, credentials mode и Keycloak auto-fill selectors для username, password и TOTP.", + "tags": [ + "configuration", + "openconnect-lite", + "autofill" + ], + "complexity": "simple" + }, + { + "id": "file:tests/smoke.sh", + "type": "file", + "name": "smoke.sh", + "filePath": "tests/smoke.sh", + "summary": "Non-live smoke suite: shell syntax, installer/uninstaller checks, Swift wiring, SSO patch snippets, config selectors и regression assertions.", + "tags": [ + "test", + "smoke", + "verification" + ], + "complexity": "complex" + } + ], + "edges": [ + { + "source": "file:install.sh", + "target": "function:install.sh:usage", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:yes_no", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:choose_credential_source_interactive", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:print_detected_state", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:choose_modules", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:download_file", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:install_homebrew_packages", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:install_openconnect_lite", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:install_cli", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:install_config", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:install_dns_cleanup", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:install_sudoers", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:install_touchid_helper", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:install_menu_bar_app", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:install_launch_agent", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:restart_running_menu_bar_app", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:install_shell_aliases", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:maybe_login_bitwarden", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:install.sh", + "target": "function:install.sh:main", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:uninstall.sh", + "target": "function:uninstall.sh:usage", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:uninstall.sh", + "target": "function:uninstall.sh:restore_openconnect_lite_patch", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:uninstall.sh", + "target": "function:uninstall.sh:remove_zshrc_block", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:uninstall.sh", + "target": "function:uninstall.sh:remove_keychain_entries", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:uninstall.sh", + "target": "function:uninstall.sh:main", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "target": "class:app/Sources/LemanaVPN/LemanaVPNApp.swift:LemanaVPNApp", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "target": "class:app/Sources/LemanaVPN/LemanaVPNApp.swift:StatusBarLabel", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "target": "class:app/Sources/LemanaVPN/LemanaVPNApp.swift:VPNMenuView", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "class:app/Sources/LemanaVPN/VPNManager.swift:VPNEvent", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "class:app/Sources/LemanaVPN/VPNManager.swift:VPNStatusResponse", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "class:app/Sources/LemanaVPN/VPNManager.swift:ModuleStatus", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "class:app/Sources/LemanaVPN/VPNManager.swift:VPNState", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "class:app/Sources/LemanaVPN/VPNManager.swift:VPNLaunchMode", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "class:app/Sources/LemanaVPN/VPNManager.swift:VPNManager", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "function:app/Sources/LemanaVPN/VPNManager.swift:refreshStatus", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "function:app/Sources/LemanaVPN/VPNManager.swift:connect", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "function:app/Sources/LemanaVPN/VPNManager.swift:disconnect", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "function:app/Sources/LemanaVPN/VPNManager.swift:parseEvent", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "function:app/Sources/LemanaVPN/VPNManager.swift:handleTermination", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "function:app/Sources/LemanaVPN/VPNManager.swift:startHealthCheck", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_module_bool", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_patches_active", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_module_status_json", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_module_human_part", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_module_status_human", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_check_status", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_patch_oc", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_normalize_totp_secret", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_persist_username", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_ensure_username", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_configure_keychain", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_ensure_keychain_credentials", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_bw_unlock", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_sync_bitwarden", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_sync_credentials", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_dns_cleanup", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "function:bin/vpn-lemanapro.sh:_filter_output", + "type": "contains", + "direction": "forward", + "weight": 1 + }, + { + "source": "document:README.md", + "target": "file:install.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "file:bin/vpn-lemanapro.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "file:uninstall.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "config:templates/openconnect-lite-config.toml", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:README.md", + "target": "file:libexec/lemana-vpn-dns-cleanup", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:AGENTS.md", + "target": "document:.agents/skills/lemana-vpn-operations/SKILL.md", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:AGENTS.md", + "target": "document:.agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:AGENTS.md", + "target": "document:.agents/skills/lemana-vpn-testing/SKILL.md", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-operations/SKILL.md", + "target": "file:install.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-operations/SKILL.md", + "target": "file:bin/vpn-lemanapro.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-operations/SKILL.md", + "target": "file:uninstall.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "target": "file:bin/vpn-lemanapro.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "target": "config:templates/openconnect-lite-config.toml", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:.agents/skills/lemana-vpn-testing/SKILL.md", + "target": "file:tests/smoke.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/goals/manual-first-auth-flow/GOAL.md", + "target": "document:docs/goals/manual-first-auth-flow/PLAN.md", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/goals/manual-first-auth-flow/PLAN.md", + "target": "file:install.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/goals/manual-first-auth-flow/PLAN.md", + "target": "file:bin/vpn-lemanapro.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/goals/manual-first-auth-flow/PLAN.md", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/goals/manual-first-auth-flow/PLAN.md", + "target": "file:tests/smoke.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "target": "file:install.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "target": "file:bin/vpn-lemanapro.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "target": "file:tests/smoke.sh", + "type": "documents", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "file:install.sh", + "target": "file:bin/vpn-lemanapro.sh", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:uninstall.sh", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "config:templates/openconnect-lite-config.toml", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:libexec/lemana-vpn-dns-cleanup", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:app/Package.swift", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:uninstall.sh", + "target": "file:bin/vpn-lemanapro.sh", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:uninstall.sh", + "target": "file:libexec/lemana-vpn-dns-cleanup", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "file:bin/vpn-lemanapro.sh", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "config:templates/openconnect-lite-config.toml", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "file:libexec/lemana-vpn-dns-cleanup", + "type": "depends_on", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:app/Package.swift", + "target": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "type": "configures", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:app/Package.swift", + "target": "file:app/Sources/LemanaVPN/VPNManager.swift", + "type": "configures", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "config:templates/openconnect-lite-config.toml", + "target": "file:bin/vpn-lemanapro.sh", + "type": "configures", + "direction": "forward", + "weight": 0.6 + }, + { + "source": "file:install.sh", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "file:uninstall.sh", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "file:bin/vpn-lemanapro.sh", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "file:app/Sources/LemanaVPN/VPNManager.swift", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + }, + { + "source": "config:templates/openconnect-lite-config.toml", + "target": "file:tests/smoke.sh", + "type": "tested_by", + "direction": "forward", + "weight": 0.5 + } + ], + "version": "1.0.0", + "project": { + "name": "Lemana VPN", + "languages": [ + "markdown", + "swift", + "shell", + "unknown", + "toml" + ], + "frameworks": [ + "SwiftUI", + "AppKit", + "openconnect-lite", + "Bitwarden CLI", + "macOS Keychain" + ], + "description": "macOS-пакет для корпоративного VPN Lemana: installer, CLI runtime, SSO/autofill через openconnect-lite, DNS cleanup wrapper и Swift menu bar app.", + "analyzedAt": "2026-06-23T06:33:02.614Z", + "gitCommitHash": "042c4d655090e0ee334208511ec63b6d909d4354" + }, + "layers": [ + { + "id": "layer:documentation-and-agent-guidance", + "name": "Документация и agent guidance", + "description": "Пользовательская документация, локальные agent skills и планы, которые описывают ожидаемые операции, safety rules и будущие изменения.", + "nodeIds": [ + "document:README.md", + "document:AGENTS.md", + "document:.agents/skills/lemana-vpn-operations/SKILL.md", + "document:.agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "document:.agents/skills/lemana-vpn-testing/SKILL.md", + "document:docs/goals/manual-first-auth-flow/GOAL.md", + "document:docs/goals/manual-first-auth-flow/PLAN.md", + "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md" + ] + }, + { + "id": "layer:installer-and-uninstaller", + "name": "Installer и uninstall слой", + "description": "Shell scripts, которые устанавливают, обновляют и удаляют локальный VPN пакет, включая dependencies, app bundle, aliases, sudoers и cleanup.", + "nodeIds": [ + "file:install.sh", + "file:uninstall.sh" + ] + }, + { + "id": "layer:runtime-cli-and-system-integration", + "name": "Runtime CLI и системная интеграция", + "description": "Основной CLI, openconnect-lite config и DNS cleanup wrapper, которые управляют SSO, credentials, VPN session status и системной очисткой DNS.", + "nodeIds": [ + "file:bin/vpn-lemanapro.sh", + "config:templates/openconnect-lite-config.toml", + "file:libexec/lemana-vpn-dns-cleanup" + ] + }, + { + "id": "layer:swift-menu-bar-app", + "name": "Swift menu bar app", + "description": "Swift Package и SwiftUI/AppKit код menu bar приложения, которое запускает CLI, показывает статус и предоставляет user-facing actions.", + "nodeIds": [ + "file:app/Package.swift", + "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "file:app/Sources/LemanaVPN/VPNManager.swift" + ] + }, + { + "id": "layer:verification", + "name": "Verification слой", + "description": "Non-live smoke suite, который закрепляет синтаксис, installer/runtime/app wiring и SSO patch/config expectations.", + "nodeIds": [ + "file:tests/smoke.sh" + ] + } + ], + "tour": [ + { + "order": 1, + "title": "Назначение проекта", + "description": "Начните с README и AGENTS, чтобы понять пользовательский контракт, состав пакета и правила безопасной работы с live VPN.", + "nodeIds": [ + "document:README.md", + "document:AGENTS.md" + ], + "languageLesson": "Markdown здесь используется как операционный runbook: таблицы путей, shell blocks и safety sections важнее обычного prose." + }, + { + "order": 2, + "title": "Установка и удаление", + "description": "Разберите installer и uninstaller: они определяют, какие артефакты попадают в систему и как их безопасно откатить.", + "nodeIds": [ + "file:install.sh", + "file:uninstall.sh" + ], + "languageLesson": "Shell strict-mode и idempotent функции помогают повторять установку без ручной чистки состояния." + }, + { + "order": 3, + "title": "Runtime CLI", + "description": "Основной runtime находится в `vpn-lemanapro.sh`: он синхронизирует credentials, применяет patches, запускает SSO и публикует JSON events.", + "nodeIds": [ + "file:bin/vpn-lemanapro.sh", + "config:templates/openconnect-lite-config.toml", + "file:libexec/lemana-vpn-dns-cleanup" + ] + }, + { + "order": 4, + "title": "SSO, credentials и autofill", + "description": "SSO skill и historical plans объясняют, почему runtime разделяет Bitwarden sync, Keychain-only flow, TOTP normalization и manual/full-manual режимы.", + "nodeIds": [ + "document:.agents/skills/lemana-vpn-sso-autofill/SKILL.md", + "document:docs/superpowers/plans/2026-05-24-keychain-totp-provider.md", + "file:bin/vpn-lemanapro.sh" + ] + }, + { + "order": 5, + "title": "Menu bar app", + "description": "Swift layer показывает user-facing поверхность: `LemanaVPNApp` строит меню, а `VPNManager` мостит app с CLI JSON events и health checks.", + "nodeIds": [ + "file:app/Package.swift", + "file:app/Sources/LemanaVPN/LemanaVPNApp.swift", + "file:app/Sources/LemanaVPN/VPNManager.swift" + ], + "languageLesson": "SwiftUI state flow здесь строится вокруг `ObservableObject` и `@Published`: изменения CLI events автоматически обновляют меню." + }, + { + "order": 6, + "title": "Проверка без live VPN", + "description": "Закончите smoke suite и testing skill: они показывают, какие проверки можно делать до любого реального подключения.", + "nodeIds": [ + "file:tests/smoke.sh", + "document:.agents/skills/lemana-vpn-testing/SKILL.md" + ] + } + ] +} \ No newline at end of file diff --git a/.understand-anything/meta.json b/.understand-anything/meta.json new file mode 100644 index 0000000..ae6a2e1 --- /dev/null +++ b/.understand-anything/meta.json @@ -0,0 +1,6 @@ +{ + "lastAnalyzedAt": "2026-06-23T06:34:14.317Z", + "gitCommitHash": "042c4d655090e0ee334208511ec63b6d909d4354", + "version": "1.0.0", + "analyzedFiles": 17 +} \ No newline at end of file