# Architecture: NODE.DC Multi-App Platform

## Цель

Собрать единую платформенную основу для Launcher, Task Manager / Plane и будущих приложений NODE.DC.

Целевой пользовательский сценарий:

1. Пользователь открывает Launcher.
2. Если сессии нет, его отправляет в платформенный login flow без публичного брендинга Authentik.
3. После логина Launcher получает identity, профиль и access projection.
4. Launcher показывает каталог приложений и состояние доступа.
5. Переход в Task Manager не требует повторного логина.
6. Прямой URL Task Manager тоже защищен.

## Роли компонентов

`Authentik` является внутренним Identity Provider / SSO layer:

- логин;
- пароль;
- активность identity;
- технические SSO-группы/entitlements;
- OIDC app access projection;
- OIDC claims;
- будущие enrollment/MFA flows, вызываемые из Launcher.

Authentik не является пользовательским control plane и не должен быть видим обычным пользователям/админам в штатном UI.

Hosted Authentik login используется только как временный dev flow. Production-вход должен быть NODE.DC-branded login facade или полностью приведенный к NODE.DC UX Authentik flow без публичного упоминания Authentik.

`Launcher` является control plane:

- входная точка пользователя;
- витрина всех приложений и состояния доступа;
- admin UI управления клиентами, пользователями, группами, инвайтами и доступами;
- мастер-данные пользователей и профиль платформы;
- backend-интеграция с Authentik API как внутренняя sync/projection;
- audit log админских действий.

`Notification Core` является платформенным владельцем уведомлений:

- принимает факты от Hub, Engine, Operational Core и будущих сервисов;
- хранит `notification_events` как факт произошедшего события;
- хранит `notification_deliveries` как адресную доставку на surface `hub`, `engine` и будущие поверхности;
- хранит server-side read-state, не завязанный на localStorage браузера;
- не использует Authentik DB и не становится владельцем доменных заявок Hub или Engine.

`Task Manager / Plane` остается отдельным приложением:

- собственная БД;
- собственные workspace/project/task/comment модели;
- собственные роли workspace/project;
- OIDC login через Authentik;
- mapping внешней identity на существующего Plane user;
- возможность работать standalone вне NODE.DC stack при сохранении стандартных Plane auth/API механизмов.

`Reverse proxy` является внешним защитным и маршрутизирующим слоем:

- единая точка входа;
- HTTPS в staging/production;
- routing по app domain;
- forward headers для Authentik;
- deny для пользователей без app access.

## Repository layout

Рабочая схема:

```text
NODEDC/
  DOC/
  platform/
    docs/
    infra/
    packages/
    tasks/

/Users/dcconstructions/Downloads/mnt/data/nodedc_launcher
/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER
```

`platform/` не забирает исходники Launcher и Plane внутрь себя. Он хранит только платформенный слой и договоренности между приложениями.

## Data ownership

Не создается единая общая таблица `users` для всех приложений.

Логическая схема:

```text
launcher_db      -> clients, users, memberships, groups, invites, app registry, access model, profiles, audit
authentik_db     -> identity/session/OIDC projection from Launcher
notification_db  -> notification_events, notification_deliveries, read-state
plane_db         -> workspace, projects, tasks, comments, app roles
future_app_db    -> доменная логика будущих приложений
```

Связь между identity и локальными пользователями выполняется через explicit mapping, а не через прямое чтение чужих таблиц.

Launcher является источником бизнес-пользователя. Authentik хранит техническую identity, необходимую для SSO, но не заменяет Launcher в администрировании клиентов, команд, доступов и профиля.

Notification recipient определяется как распознанный platform subject. Для email без platform user record delivery не создается: source flow может хранить pending intent/invite, а delivery появляется после регистрации/создания platform identity. Pending access-request user, который уже может войти в Hub и видеть витрину, считается допустимым recipient для `hub` delivery. Surface-specific delivery, например `engine`, создается только когда пользователь имеет доступ к этой surface.

## App standalone rule

Подключаемые приложения не должны становиться невынимаемыми частями NODE.DC.

Для Plane это означает:

- NODE.DC интеграция добавляется как адаптерный слой: OIDC provider, external identity link, app access projection и будущий service adapter;
- доменные таблицы Plane не становятся частью Launcher DB;
- Launcher не читает и не пишет Plane DB напрямую;
- управление workspace/project/task/comment остается внутри Plane;
- интеграция с Plane выполняется через публичные Plane API, API tokens или явно выделенные adapter endpoints;
- стандартные Plane auth/API механизмы не удаляются без отдельного решения, чтобы можно было поставить Plane клиенту standalone.

Если клиенту нужен только Task Manager, целевая поставка должна позволять развернуть Plane отдельно, отключить NODE.DC Launcher/Auth projection и оставить штатную модель Plane.

## Auth flow

Для приложений, которые контролируются кодом:

- OIDC Authorization Code Flow + PKCE;
- backend/session или BFF layer;
- JWT/JWKS validation server-side;
- проверка `issuer`, `audience`, `exp`, `sub`;
- проверка app access projection group/entitlement;
- локальный user profile или external identity link.

Для legacy/временных приложений допускается reverse proxy forward-auth, но это временный внешний слой, а не единственная долгосрочная модель.

## Plane migration rule

Существующий Plane user нельзя пересоздавать.

Нужен mapping:

```text
authentik_user.sub -> existing plane_user.id
```

Plane должен логинить существующего пользователя по link, сохраняя все старые workspace, assignee, owner, created_by, comments и attachments.
