# Security Checklist

Staging path and runbook: `docs/STAGING_SECURITY_PLAN.md`.
DevOps handoff: `docs/DEVOPS_SECURITY_HANDOFF.md`.
Service catalog UX rules: `docs/SERVICE_CATALOG_UX_RULES.md`.

## Network

- [x] Local dev compose публикует только reverse proxy port.
- [ ] Postgres не опубликован наружу в staging/production.
- [ ] Redis не опубликован наружу в staging/production.
- [ ] MinIO/storage не опубликован наружу в staging/production.
- [ ] Внутренние API не доступны напрямую извне.
- [x] Authentik получает `X-Forwarded-Proto`, `X-Forwarded-For`, `Host` через Caddy.
- [x] Caddy reverse proxy сохраняет HTTP/1.1/WebSocket upgrade behavior для upstream.

## Authentik

- [ ] Каждое приложение имеет отдельный Authentik Application.
- [ ] Каждое приложение имеет отдельный Provider.
- [ ] Для каждого приложения задана отдельная access policy.
- [ ] Группы app access заведены отдельно от app-local ролей.
- [ ] MFA/enrollment policy вынесены в отдельный этап.
- [x] Authentik local compose не публикует server/worker/Postgres ports напрямую.

## Launcher

- [ ] Authentik service token хранится только server-side.
- [ ] Frontend не получает service token.
- [ ] Synology Launcher использует platform Authentik alias `http://nodedc-platform-authentik-server:9000`, не неоднозначный `http://authentik-server:9000`.
- [ ] Admin endpoints требуют `nodedc:superadmin` или `nodedc:launcher:admin`.
- [ ] Все admin actions пишутся в audit log.
- [ ] Удаление пользователя реализовано как deactivate/disable, не hard delete.
- [x] Local runtime не отдает `storage/launcher-data.json` напрямую через public static route.
- [x] Local runtime требует user session для `/api/storage/data`.

## Cross-app session sync

- [x] Общий live logout path зафиксирован как `nodedc:session:logout` через Launcher session-sync/frontchannel.
- [x] BIM Viewer подключён к logout path и по logout должен понижать UI до guest/limited controls.
- [x] BIM login-sync marker не является auth-token и требует revalidation через Launcher.
- [ ] Описан общий `ndcauth.session` contract для login/logout/change, а не только BIM-first slice.
- [ ] HUB/OPS/ENGINE/BIM проходят browser matrix: login/logout из любого surface обновляет уже открытые приложения без refresh.
- [ ] Session sync события имеют audit/observability без user secrets в логах.

## Plane

- [ ] Перед изменениями сделан backup DB/env/uploads/storage.
- [ ] Существующий Plane user не пересоздается.
- [ ] `owner_id`, `created_by`, `assignee_id`, `member_id` не меняются без отдельной миграции.
- [ ] Публичный signup отключен.
- [ ] Лишние обходные auth сценарии закрыты или явно оставлены как временные.
- [ ] OIDC login проверяет state/nonce/token.
- [ ] `authentik_sub` связан с существующим `plane_user_id`.

## Tokens and secrets

- [ ] Secrets не попадают в git.
- [ ] Access/refresh tokens не логируются.
- [ ] Session cookies имеют `secure=true` в staging/production.
- [ ] В production включены HTTPS и HSTS.
- [x] Local internal API token отделен от `PLANE_OIDC_CLIENT_SECRET`.
- [x] Launcher internal access API отклоняет запросы без token, с неверным token и со старым OIDC client secret.
- [x] Tasker internal logout API отклоняет запросы без token и со старым OIDC client secret.

## Acceptance scenarios

- [x] Без логина Launcher отправляет в Authentik.
- [ ] Пользователь без Task Manager app access видит карточку Task Manager в Launcher, но не может открыть сервис.
- [x] Пользователь без Task Manager app access получает deny в Tasker access middleware при прямом доступе.
- [ ] Пользователь с доступом открывает Task Manager.
- [ ] Старый Plane admin после OIDC видит старые workspace/tasks/comments.
- [ ] Деактивированный пользователь теряет доступ.
- [x] Hard-deleted/annulled user теряет stale Tasker identity link и старая unlinked-сессия отзывается middleware.
- [x] Hard-deleted/annulled user удаляется из active Tasker workspace/project members и issue assignees.
- [x] Self-host Tasker workspace invite создает pending request в Launcher, а launcher-managed workspace не принимает self-service invite request.
- [x] Admin action появляется в audit log.
- [x] Повторный accept уже принятого invite отклоняется.
