{ "nodes": [ { "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: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 } ] }