2037 lines
60 KiB
JSON
2037 lines
60 KiB
JSON
{
|
||
"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"
|
||
]
|
||
}
|
||
]
|
||
} |