# Создание рабочей области SaaS на Elang

Эталонное приложение `elang/saas` объединяет подтверждённые учётные записи, организации, проверки ролей, проекты, закрытые файлы, приглашения, входящие уведомления, API с областями доступа, аутентифицированные потоки событий, безопасность учётной записи и эксплуатационные средства администратора. Это запускаемая отправная точка для командного продукта. Биллинг, платёжные регистры и отраслевая сертификация остаются отдельными задачами предметной области.

## Установка и запуск

```bash
composer create-project elang/saas workspace dev-main
cd workspace
php elang doctor
php elang serve
```

Обработчики создания проекта Composer генерируют ключ приложения и подготавливают миграции и таблицы платформы. Для проекта, созданного из исходного кода, сначала выполните `composer install`, `php elang key:generate`, `php elang migrate` и `php elang platform:setup`. Держите корневой каталог приложения закрытым и открывайте только `public/`.

Откройте `/register`, создайте пользователя и подтвердите локальную учётную запись через `/_elang/studio/mail`. Откройте `/workspace`. Зарегистрируйте вторую учётную запись в отдельном контексте браузера, чтобы проверить поведение приглашений и изоляции. Для развёртывания на нескольких хостах используйте PostgreSQL или MySQL вместе с общим Redis; SQLite и локальное хранилище полезны для разработки.

## Пройдите первый сценарий команды

1. Создайте организацию с коротким именем. Её создатель становится владельцем.
2. Добавьте проект. Проекты начинают в `planned`; переводите их в `active` или `done`.
3. Пригласите другой подтверждённый адрес почты как участника или наблюдателя. Передайте этому человеку сгенерированную закрытую ссылку.
4. Примите приглашение, войдя под владельцем совпадающего адреса почты.
5. Убедитесь, что наблюдатель может читать, но не может менять проекты или загружать файлы.
6. Загрузите закрытый документ или выберите обработку изображения для JPEG/PNG/WebP.
7. Откройте созданную ссылку скачивания с аутентификацией. Удалите участника и убедитесь, что доступ ему закрыт.
8. Просмотрите обновления входящих сообщений, устройства учётной записи и поведение аудита.

Ссылки приглашений истекают через семь дней и используются один раз. Повторная выдача заменяет старое приглашение для той же команды и электронной почты. Пример показывает закрытую ссылку для намеренной передачи; он не отправляет внешнее письмо приглашения автоматически.

## Понимание записи проектов

`app/Projects.php` применяет одинаковое явное ограничение арендатора к просмотру списка, обновлению и удалению. `Teams::within()` заново загружает членство и удерживает блокировку организации на протяжении каждой транзакции SQL. Версии проектов реализуют оптимистическое управление конкурентным доступом: старая форма не может незаметно перезаписать более новое изменение. Устаревшая версия возвращает 409 и предлагает пользователю обновить страницу.

Изменения проекта и соответствующее событие реального времени фиксируются вместе через одно подключение SQL. Данные событий содержат идентификатор проекта; потребители заново загружают текущий авторизованный снимок состояния. Записи аудита включают безопасные ID и имена действий вместо текста проектов. Проекты, метаданные файлов, уведомления и членство используют отдельные таблицы с явной принадлежностью.

Пример выводит последние 100 проектов, файлов и входящих сообщений. Для более крупного продукта добавьте постраничную навигацию, поиск, квоты, валидацию предметной области и специальные индексы. Репозиторий моделей фреймворка уже поддерживает постраничную навигацию; не принимайте ограниченный экран примера за неограниченное получение записей.

## Клиенты API и обмена в реальном времени

Приложение SaaS сохраняет API заметок и добавляет:

| Метод | Путь | Необходимая область доступа |
| --- | --- | --- |
| GET / POST | `/api/teams` | `teams:read` / `teams:write` |
| GET / POST | `/api/teams/{team}/projects` | `teams:read` / `teams:write` |
| PUT / DELETE | `/api/teams/{team}/projects/{project}` | `teams:write` |

Операции записи с аутентификацией через cookie требуют CSRF; bearer-токены с областями доступа работают для серверных и мобильных интеграций. Область токена не заменяет проверки членства и роли. Посторонний получает 404, а участник с правом только чтения не может писать даже с токеном области записи. PUT передаёт title/status и целочисленный version; DELETE передаёт текущий целочисленный version как JSON. Действительный Idempotency-Key защищает повторные попытки идентичной записи JSON на поддерживаемых эндпоинтах.

Для обновлений браузера используйте аутентифицированный SSE по `/workspace/team/{team}/events`. Поток освобождает блокировку сессии и периодически перепроверяет текущую версию учётной записи и членство. Он закрывается после ограниченного окна ответа и должен подключаться повторно. Сохраняйте курсор события и обновляйте список проектов после изменения. За пределами сохранённой истории загружайте новый снимок состояния. Этот пример не предоставляет разрешения WebSocket для команд; отдельный API заметок демонстрирует аутентифицированный WebSocket для личных каналов.

## Эксплуатация приложения

Подготовьте администратора через доверенный терминал; ввод пароля скрыт:

```bash
php elang user:create owner@example.com --admin --verified
php elang queue:work
php elang outbox:work
```

Используйте `/security`, чтобы включить приложение-аутентификатор и зарегистрировать ключи доступа. Под подтверждённой учётной записью администратора используйте `/operations` для просмотра состояния очереди, метаданных неудачных заданий, сигналов активности обработчиков, накопления outbox и агрегатов HTTP. Настройте реальный почтовый транспорт перед обработкой писем очереди. Запускайте обработчики под управлением диспетчера процессов и сохраняйте одинаковую регистрацию заданий между веб-версией и версией обработчиков.

Перед рабочей эксплуатацией проверьте восстановление резервных копий, восстановление учётных данных, изоляцию арендаторов, одновременные изменения, отзыв членства, поведение очереди при сбоях и повторных попытках, сверку хранилища, ограничения частоты и реалистичный аутентифицированный трафик. Определите целевые показатели уровня сервиса и измеряйте весь стек. Elang остаётся выпуском для разработки; неизмеренная пропускная способность или универсальное превосходство над фреймворками не обещаются.

Связанные разделы: [команды](/docs/v0.1/tenancy), [файлы](/docs/v0.1/files), [уведомления](/docs/v0.1/notifications), [эксплуатация](/docs/v0.1/observability) и [подготовка выпусков](/docs/v0.1/releases).
