From 665625ecd8abd2c551382e38ec625f2bf9e13f26 Mon Sep 17 00:00:00 2001 From: Andrey Lutsenko Date: Sun, 14 Jun 2026 21:42:23 +1000 Subject: [PATCH] =?UTF-8?q?chore:=20sync=20kalinamall=20(README=20=D0=B8?= =?UTF-8?q?=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=B7=D0=B5=D1=80=D0=BA?= =?UTF-8?q?=D0=B0=D0=BB=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cursor/rules/00-always-read-rules.mdc | 28 ++++++ .cursor/rules/01-context-control.mdc | 24 +++++ .cursor/rules/agent-monitors-version-bump.mdc | 18 ++++ .cursor/rules/csharp-spec.mdc | 12 +++ .cursor/rules/gitea-home-api.mdc | 37 ++++++++ .cursor/rules/repo-policy.mdc | 18 ++++ .cursorignore | 52 +++++++++++ scripts/check-github-clean.sh | 52 +++++++++++ scripts/push-remotes.sh | 65 ++++++++++---- scripts/readme/github.md | 87 ------------------- scripts/readme/home.md | 87 ------------------- 11 files changed, 288 insertions(+), 192 deletions(-) create mode 100644 .cursor/rules/00-always-read-rules.mdc create mode 100644 .cursor/rules/01-context-control.mdc create mode 100644 .cursor/rules/agent-monitors-version-bump.mdc create mode 100644 .cursor/rules/csharp-spec.mdc create mode 100644 .cursor/rules/gitea-home-api.mdc create mode 100644 .cursor/rules/repo-policy.mdc create mode 100644 .cursorignore create mode 100755 scripts/check-github-clean.sh delete mode 100644 scripts/readme/github.md delete mode 100644 scripts/readme/home.md diff --git a/.cursor/rules/00-always-read-rules.mdc b/.cursor/rules/00-always-read-rules.mdc new file mode 100644 index 0000000..35460ae --- /dev/null +++ b/.cursor/rules/00-always-read-rules.mdc @@ -0,0 +1,28 @@ +--- +description: Перед работой — прочитай все применимые rules +alwaysApply: true +--- + +# Всегда читай правила + +Перед **любой** задачей (код, git, push, релиз, ответ пользователю): + +1. **Прочитай все применимые rules** — user rules, workspace `.cursor/rules/`, особенно с `alwaysApply: true`. +2. **Не начинай работу**, пока не понял ограничения из rules (git, Cursor в репо, version-bump, язык ответа и т.д.). +3. **При конфликте** запроса пользователя и rule — остановись, объясни конфликт, спроси подтверждение. + +## Обязательные проверки по типу задачи + +| Задача | Перед действием прочитай / проверь | +|--------|-------------------------------------| +| `git commit` / `push` | `no-cursor-in-repositories` — нет `.cursor/` в staged; `.gitignore` содержит `.cursor/` | +| Push в `home` | `gitea-home-api` — сначала API, потом SSH push | +| Bump версии | `version-bump` (+ `version-bump-rdp` / `version-bump-ssh` для агентских мониторов) | +| Коммит | `git log -1 --format=fuller` — нет `cursoragent`, `Co-authored-by: Cursor` | + +## Если rule нарушен + +- **Не push**, не «доделывай быстрее». +- Исправь (amend / filter / commit-tree), затем снова проверь лог. + +Правила важнее скорости выполнения задачи. \ No newline at end of file diff --git a/.cursor/rules/01-context-control.mdc b/.cursor/rules/01-context-control.mdc new file mode 100644 index 0000000..b1f0ebc --- /dev/null +++ b/.cursor/rules/01-context-control.mdc @@ -0,0 +1,24 @@ +--- +description: Git, контекст файлов и формат ответов +alwaysApply: true +--- + +# Контекст и дисциплина + +## Git + +- **Не** `git commit` / **не** `git push` без явной команды пользователя. +- Перед commit: покажи `git diff --stat`, дождись подтверждения. +- Conventional Commits: `feat:`, `fix:`, `docs:`, `refactor:`. + +## Контекст + +- Файлы: `@`, открытые вкладки, явные пути — не сканируй весь репо без запроса. +- Не грузи файлы >500 строк без необходимости. +- Локальные копии; не качай пакеты/URL без ошибки сборки или явного запроса. + +## Ответы + +- Язык: **русский** (если пользователь не переключился). +- По коду — diff/фрагменты, не дублируй неизменённые блоки. +- Без воды, но достаточно полно для понимания (не обрезай сложные ответы до одной строки). diff --git a/.cursor/rules/agent-monitors-version-bump.mdc b/.cursor/rules/agent-monitors-version-bump.mdc new file mode 100644 index 0000000..1e69d89 --- /dev/null +++ b/.cursor/rules/agent-monitors-version-bump.mdc @@ -0,0 +1,18 @@ +--- +description: Bump версии RDP/SSH агентов — иначе ПК не обновятся +globs: **/Login_Monitor.ps1,**/Deploy-LoginMonitor.ps1,**/Sac-Client.ps1,**/ssh-monitor,**/sac-client.sh,**/update_ssh_monitor.sh +alwaysApply: false +--- + +# Версии агентских мониторов + +Любая **существенная правка** без bump **не доедет** до компьютеров. + +| Стек | Файлы | Поле / файл версии | +|------|-------|-------------------| +| RDP | `Login_Monitor.ps1`, `version.txt` | `$ScriptVersion` = `version.txt` | +| SSH | `ssh-monitor`, `version.txt` | `SSH_MONITOR_VERSION` = `version.txt` | + +Подробности: `version-bump-rdp.mdc`, `version-bump-ssh.mdc`. + +**SAC backend:** `backend/app/version.py` (`APP_VERSION`) — отдельный релиз, на агенты ПК не влияет. diff --git a/.cursor/rules/csharp-spec.mdc b/.cursor/rules/csharp-spec.mdc new file mode 100644 index 0000000..f49a451 --- /dev/null +++ b/.cursor/rules/csharp-spec.mdc @@ -0,0 +1,12 @@ +--- +description: Краткий C# без лишних токенов в выводе +globs: **/*.cs +alwaysApply: false +--- + +# C# — компактный вывод + +- File-scoped namespaces, pattern matching, target-typed `new()`, primary constructors где уместно. +- Без XML-комментариев, `#region`, лишних `using`. +- Без `Console.WriteLine` / debug-log, если задача не про логирование. +- Expression-bodied members, где читаемо. diff --git a/.cursor/rules/gitea-home-api.mdc b/.cursor/rules/gitea-home-api.mdc new file mode 100644 index 0000000..f2e74f1 --- /dev/null +++ b/.cursor/rules/gitea-home-api.mdc @@ -0,0 +1,37 @@ +--- +description: Gitea home — репо через API, не вручную в вебе +alwaysApply: true +--- + +# Gitea home (papatramp) + +При push в **`home`**, настройке remotes или первом заливе — **через Gitea API**. Не проси создать репо вручную при `Push to create is not enabled` / `Cannot find repository`. + +## Пути (локально, не в git-репо) + +| Назначение | Путь | +|------------|------| +| Конфиг API (секреты) | `$HOME\CursorRules\local\papatramp-gitea.conf` | +| Remotes | `$HOME\CursorRules\scripts\Set-GitRemotes.ps1` | +| Создать репо на home | `$HOME\CursorRules\scripts\Ensure-GiteaHomeRepo.ps1` | + +`init-cursor` копирует в репо **только `*.mdc`**. + +SSH **`home`**: `ssh://git@git.papatramp.lan:2222/PapaTramp/.git` + +## Алгоритм + +1. `GET {GiteaApiUrl}/api/v1/repos/PapaTramp/{RepoName}` — Basic Auth из конфига. +2. Если **404** — `POST {GiteaApiUrl}/api/v1/user/repos` (или `.../orgs/PapaTramp/repos`), тело: `{ "name": "", "private": true, "auto_init": false }`. + Или: `Ensure-GiteaHomeRepo.ps1 -RepoName `. +3. `git push home ` (SSH). + +## Запрещено + +- «Создайте репо в Gitea сами» без попытки API. +- Коммитить `papatramp-gitea.conf`, пароли, временные скрипты с credentials. +- HTTPS/`origin` для home вместо remote **`home`**. + +## API недоступен + +Сообщи, что LAN/API (`192.168.128.48:3000`) недоступен — VPN/сеть. Не отправляй в веб-интерфейс. diff --git a/.cursor/rules/repo-policy.mdc b/.cursor/rules/repo-policy.mdc new file mode 100644 index 0000000..cfeca78 --- /dev/null +++ b/.cursor/rules/repo-policy.mdc @@ -0,0 +1,18 @@ +--- +description: Политика remotes и push — kalinamall/home/github +alwaysApply: true +--- + +# Git remotes (kalinamall.ru) + +- **kalinamall** — основной Gitea, полный код и секреты. `git push kalinamall main`. +- **home** — домашний Gitea, полная копия. +- **github** — только резерв **без секретов**. Перед push: `check-no-secrets.sh`. +- Remotes только **SSH** (`ssh://`, `git@`). HTTPS и `origin` не использовать. +- Не коммитить в GitHub: `.env`, ключи, пароли, токены, `google-services.json`, prod credentials. +- См. `docs/repo-policy.md` в reverse-proxy. + +# Cursor + +- Отвечать на русском, если пользователь пишет по-русски. +- Коммиты только по явной просьбе пользователя. diff --git a/.cursorignore b/.cursorignore new file mode 100644 index 0000000..80d8e9c --- /dev/null +++ b/.cursorignore @@ -0,0 +1,52 @@ +node_modules/ +bower_components/ +jspm_packages/ +.npm/ +vendor/ +.pnpm-store/ +.venv/ +venv/ +env/ +ENV/ +.env/ +dist/ +build/ +out/ +.next/ +.nuxt/ +.docusaurus/ +.cache/ +.sass-cache/ +.turbo/ +target/ +bin/ +obj/ +.git/ +.svn/ +.idea/ +.vscode/ +.cursor/ +*.log +*.png +*.jpg +*.jpeg +*.gif +*.svg +*.ico +*.mp4 +*.mp3 +*.pdf +*.zip +*.tar.gz +*.rar +*.exe +*.dll +*.woff +*.woff2 +*.ttf +*.eot +package-lock.json +yarn.lock +pnpm-lock.yaml +poetry.lock + diff --git a/scripts/check-github-clean.sh b/scripts/check-github-clean.sh new file mode 100755 index 0000000..bf94d7f --- /dev/null +++ b/scripts/check-github-clean.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# Перед push на github: нет internal URL и файлов других зеркал. +set -Eeuo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT" + +PATTERNS=( + 'git\.kalinamall\.ru' + 'git\.papatramp\.ru' + 'papatramp\.lan' + '192\.168\.' + 'kalinamall/main' + 'push.*kalinamall' +) + +scan_files() { + local hits=0 + local files + files=$(git ls-files) + while read -r f; do + [[ -z $f ]] && continue + [[ -f $f ]] || continue + case $f in + scripts/check-github-clean.sh | scripts/push-remotes.sh) continue ;; + esac + for pat in "${PATTERNS[@]}"; do + if grep -qE "$pat" "$f" 2>/dev/null; then + echo " INTERNAL? $f (pattern: $pat)" + hits=$((hits + 1)) + fi + done + done <<<"$files" + return $hits +} + +echo "[check-github-clean] сканирование tracked-файлов" +n=0 +scan_files || n=$? +if [[ $n -gt 0 ]]; then + echo "[check-github-clean] найдено: $n" + exit 1 +fi + +for f in scripts/readme/kalinamall.md scripts/readme/home.md; do + if [[ -f $f ]]; then + echo " FORBIDDEN FILE: $f" + exit 1 + fi +done + +echo "[check-github-clean] OK" diff --git a/scripts/push-remotes.sh b/scripts/push-remotes.sh index 88ba407..6fae790 100755 --- a/scripts/push-remotes.sh +++ b/scripts/push-remotes.sh @@ -1,46 +1,75 @@ #!/usr/bin/env bash -# Push README.md с правильным содержимым на каждый remote (ветки README расходятся). +# Синхронизация main на kalinamall / home / github: свой README и только свои readme-шаблоны. set -Eeuo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" CHECK_SECRETS="${CHECK_SECRETS:-$HOME/Documents/Cursor/Projects/Answer.and.other.shit/guides/init.new.comps/scripts/check-no-secrets.sh}" +CHECK_GITHUB="${CHECK_GITHUB:-$ROOT/scripts/check-github-clean.sh}" -push_readme() { +sync_remote() { local remote=$1 - local template=$2 - local message=$3 - local branch="push-${remote}-readme" + local readme_template=$2 + local branch="sync-${remote}" + shift 2 + local -a remove=( "$@" ) git fetch "$remote" git checkout -B "$branch" "${remote}/main" - cp "$template" README.md - git add README.md + git checkout main -- . + cp "$readme_template" README.md + + for f in "${remove[@]}"; do + if [[ -e $f ]]; then + rm -rf "$f" + fi + done + + git add -A if git diff --cached --quiet; then - echo "[push-readme] $remote: README без изменений" + echo "[push-remotes] $remote: без изменений" else - git commit -m "$message" + git commit -m "chore: sync $remote (README и файлы зеркала)" fi - if [[ $remote == github ]] && [[ -f $CHECK_SECRETS ]]; then - bash "$CHECK_SECRETS" github + + if [[ $remote == github ]]; then + if [[ -f $CHECK_GITHUB ]]; then + bash "$CHECK_GITHUB" + fi + if [[ -f $CHECK_SECRETS ]]; then + bash "$CHECK_SECRETS" github + fi fi + git push "$remote" "${branch}:main" git checkout main git branch -D "$branch" } -echo "[push-readme] kalinamall: push текущего main" -git push kalinamall main +echo "[push-remotes] kalinamall" +sync_remote kalinamall "$ROOT/scripts/readme/kalinamall.md" \ + scripts/readme/github.md \ + scripts/readme/home.md -push_readme home "$ROOT/scripts/readme/home.md" "docs: README для home (git.papatramp.ru)" -push_readme github "$ROOT/scripts/readme/github.md" "docs: README для GitHub (без internal URL)" +echo "[push-remotes] home" +sync_remote home "$ROOT/scripts/readme/home.md" \ + scripts/readme/github.md \ + scripts/readme/kalinamall.md \ + scripts/push-remotes.sh \ + scripts/check-github-clean.sh + +echo "[push-remotes] github" +sync_remote github "$ROOT/scripts/readme/github.md" \ + scripts/readme/kalinamall.md \ + scripts/readme/home.md \ + scripts/push-remotes.sh \ + scripts/check-github-clean.sh cp "$ROOT/scripts/readme/kalinamall.md" README.md git add README.md if ! git diff --cached --quiet; then - git commit -m "docs: README для kalinamall (рабочая копия)" + git commit -m "docs: README kalinamall (рабочая копия main)" fi -git push kalinamall main -echo "[push-readme] готово." +echo "[push-remotes] готово." diff --git a/scripts/readme/github.md b/scripts/readme/github.md deleted file mode 100644 index 6c205a7..0000000 --- a/scripts/readme/github.md +++ /dev/null @@ -1,87 +0,0 @@ -# Seaca - -**Seaca** (Security Event Alert Center App) — нативный мобильный клиент **Security Alert Center (SAC)** для Android. - -Оператор видит те же данные, что и в веб-интерфейсе SAC: обзор, события, отчёты, проблемы и хосты. Push-уведомления приходят по тем же правилам severity и cooldown, что Telegram/email/webhook на сервере. Управление пользователями, каналами оповещений и привязкой устройств — **только в веб-SAC** (раздел «Настройки»). - -## Связанные репозитории - -| Репозиторий | Роль | -|-------------|------| -| security-alert-center | Сервер SAC: API, UI, оповещения, управление мобильными устройствами | -| ssh-monitor | Агент Linux | -| RDP-login-monitor | Агент Windows | - -| Репозиторий | URL | -|-------------|-----| -| security-alert-center | https://github.com/PTah/security-alert-center | -| ssh-monitor | https://github.com/PTah/ssh-monitor | -| RDP-login-monitor | https://github.com/PTah/RDP-login-monitor | -## Стек - -| Слой | Технология | -|------|------------| -| UI | Kotlin, Jetpack Compose, Material 3 | -| Сеть | Retrofit / OkHttp, Kotlin Serialization | -| Хранение | DataStore + Android Keystore (токены, URL сервера) | -| Push | **Firebase Cloud Messaging (FCM)** | -| Минимум SDK | Android 8.0 (API 26) | - -## Что есть в приложении - -- Обзор, события, отчёты, проблемы, хосты (списки и карточки с читаемыми полями) -- Pull-to-refresh на обзоре и в списках -- Фильтры событий и проблем (severity, status) -- Формат даты/времени на выбор (слэш, дефис, точка или системный локаль) -- Ack / Resolve для роли `operator` и выше -- Push с переходом в карточку события или problem; режимы: со звуком, без звука, выключено -- Выбор звука уведомления: системный или свой (ringtone picker) -- Биометрическая блокировка при **запуске** и при возврате в приложение -- Экран «Моё устройство»: сервер, пользователь, роль, версия, настройки push, выход -- Первичная привязка к серверу по **коду регистрации**, который выдаёт администратор в веб-SAC - -## Чего нет в приложении (только веб) - -- Управление пользователями SAC -- Настройки каналов (Telegram, SMTP, webhook), severity, policy -- Выдача и отзыв кодов регистрации, список устройств, способ входа на устройство — всё это в **Настройки → Мобильные устройства** на сервере - -## Привязка телефона к серверу - -1. Администратор в веб-SAC включает «Разрешать подключение мобильных устройств». -2. Создаёт **код регистрации** для пользователя (срок действия, одноразовый или с лимитом использований). -3. Оператор в Seaca: URL API SAC (выдаёт администратор) + код + логин/пароль (если код не привязан к предварительной сессии). -4. Приложение регистрирует FCM-токен; устройство появляется в списке на сервере. -5. Администратор может отключить устройство, сменить разрешённый способ входа, переименовать. - -Подробный план — [docs/ROADMAP.md](docs/ROADMAP.md). - -## Статус - -**Версия:** `0.5.7` (Android: Kotlin, Compose; enroll, UI, ack/resolve, FCM, биометрия, звук push, форматы даты) - -## Документация - -| Документ | Назначение | -|----------|------------| -| [docs/operator-guide.md](docs/operator-guide.md) | Инструкция для оператора | -| [docs/ROADMAP.md](docs/ROADMAP.md) | План разработки | - -## Сборка - -Требуется **JDK 17+** (Android Studio JBR или отдельная установка) и Android SDK (`local.properties` с `sdk.dir=…`). - -```bash -# Опционально: конфиг Firebase в app/ (шаблон *.example, рабочий файл не в git) — для FCM -./gradlew assembleDebug -# Windows: -gradlew.bat assembleDebug -``` - -APK: `app/build/outputs/apk/debug/app-debug.apk` - -Без конфига Firebase приложение собирается, но FCM не инициализируется (просмотр данных работает). - -## Лицензия - -Как у остальных репозиториев семейства SAC (уточняется владельцем проекта). diff --git a/scripts/readme/home.md b/scripts/readme/home.md deleted file mode 100644 index 2a7e0fe..0000000 --- a/scripts/readme/home.md +++ /dev/null @@ -1,87 +0,0 @@ -# Seaca - -**Seaca** (Security Event Alert Center App) — нативный мобильный клиент **Security Alert Center (SAC)** для Android. - -Оператор видит те же данные, что и в веб-интерфейсе SAC: обзор, события, отчёты, проблемы и хосты. Push-уведомления приходят по тем же правилам severity и cooldown, что Telegram/email/webhook на сервере. Управление пользователями, каналами оповещений и привязкой устройств — **только в веб-SAC** (раздел «Настройки»). - -## Связанные репозитории - -| Репозиторий | Роль | -|-------------|------| -| security-alert-center | Сервер SAC: API, UI, оповещения, управление мобильными устройствами | -| ssh-monitor | Агент Linux | -| RDP-login-monitor | Агент Windows | - -| Репозиторий | URL | -|-------------|-----| -| security-alert-center | https://git.papatramp.ru/PapaTramp/security-alert-center | -| ssh-monitor | https://git.papatramp.ru/PapaTramp/ssh-monitor | -| RDP-login-monitor | https://git.papatramp.ru/PapaTramp/RDP-login-monitor | -## Стек - -| Слой | Технология | -|------|------------| -| UI | Kotlin, Jetpack Compose, Material 3 | -| Сеть | Retrofit / OkHttp, Kotlin Serialization | -| Хранение | DataStore + Android Keystore (токены, URL сервера) | -| Push | **Firebase Cloud Messaging (FCM)** | -| Минимум SDK | Android 8.0 (API 26) | - -## Что есть в приложении - -- Обзор, события, отчёты, проблемы, хосты (списки и карточки с читаемыми полями) -- Pull-to-refresh на обзоре и в списках -- Фильтры событий и проблем (severity, status) -- Формат даты/времени на выбор (слэш, дефис, точка или системный локаль) -- Ack / Resolve для роли `operator` и выше -- Push с переходом в карточку события или problem; режимы: со звуком, без звука, выключено -- Выбор звука уведомления: системный или свой (ringtone picker) -- Биометрическая блокировка при **запуске** и при возврате в приложение -- Экран «Моё устройство»: сервер, пользователь, роль, версия, настройки push, выход -- Первичная привязка к серверу по **коду регистрации**, который выдаёт администратор в веб-SAC - -## Чего нет в приложении (только веб) - -- Управление пользователями SAC -- Настройки каналов (Telegram, SMTP, webhook), severity, policy -- Выдача и отзыв кодов регистрации, список устройств, способ входа на устройство — всё это в **Настройки → Мобильные устройства** на сервере - -## Привязка телефона к серверу - -1. Администратор в веб-SAC включает «Разрешать подключение мобильных устройств». -2. Создаёт **код регистрации** для пользователя (срок действия, одноразовый или с лимитом использований). -3. Оператор в Seaca: URL API SAC (выдаёт администратор) + код + логин/пароль (если код не привязан к предварительной сессии). -4. Приложение регистрирует FCM-токен; устройство появляется в списке на сервере. -5. Администратор может отключить устройство, сменить разрешённый способ входа, переименовать. - -Подробный план — [docs/ROADMAP.md](docs/ROADMAP.md). - -## Статус - -**Версия:** `0.5.7` (Android: Kotlin, Compose; enroll, UI, ack/resolve, FCM, биометрия, звук push, форматы даты) - -## Документация - -| Документ | Назначение | -|----------|------------| -| [docs/operator-guide.md](docs/operator-guide.md) | Инструкция для оператора | -| [docs/ROADMAP.md](docs/ROADMAP.md) | План разработки | - -## Сборка - -Требуется **JDK 17+** (Android Studio JBR или отдельная установка) и Android SDK (`local.properties` с `sdk.dir=…`). - -```bash -# Опционально: конфиг Firebase в app/ (шаблон *.example, рабочий файл не в git) — для FCM -./gradlew assembleDebug -# Windows: -gradlew.bat assembleDebug -``` - -APK: `app/build/outputs/apk/debug/app-debug.apk` - -Без конфига Firebase приложение собирается, но FCM не инициализируется (просмотр данных работает). - -## Лицензия - -Как у остальных репозиториев семейства SAC (уточняется владельцем проекта).