2026-07-30 21:44:47 +03:00
# Переход домена auth с Level 1
2026-07-30 18:45:54 +03:00
2026-08-02 22:53:05 +03:00
> Проверочный пример локального перехода от доменного модуля к пакету с Domain API, ports, adapters и default assembly.
2026-07-30 18:45:54 +03:00
2026-07-30 21:44:47 +03:00
## Связанные правила
2026-07-30 18:45:54 +03:00
2026-07-30 21:44:47 +03:00
- [`SLM-L2-DEPENDENCY-A012` ](../../rules/level-2.md#slm-l2-dependency-a012 )
2026-08-02 22:53:05 +03:00
- [`SLM-L2-API-R005` ](../../rules/level-2.md#slm-l2-api-r005 )
- [`SLM-L2-API-A019` ](../../rules/level-2.md#slm-l2-api-a019 )
2026-07-30 21:44:47 +03:00
- [`SLM-L2-ASSEMBLY-A020` ](../../rules/level-2.md#slm-l2-assembly-a020 )
2026-07-30 20:48:05 +03:00
- [`SLM-L2-ADAPTER-R021` ](../../rules/level-2.md#slm-l2-adapter-r021 )
2026-08-02 22:53:05 +03:00
- [`SLM-L2-API-A022` ](../../rules/level-2.md#slm-l2-api-a022 )
- [`SLM-L2-DOMAIN-A026` ](../../rules/level-2.md#slm-l2-domain-a026 )
- [`SLM-L2-PORT-R027` ](../../rules/level-2.md#slm-l2-port-r027 )
- [`SLM-L2-STATE-R028` ](../../rules/level-2.md#slm-l2-state-r028 )
2026-07-30 18:45:54 +03:00
## Исходная форма Level 1
```text
2026-07-30 21:44:47 +03:00
domains/
├── auth/ # Доменный модуль
│ ├── hooks/
│ ├── services/
│ ├── stores/
│ ├── ui/
│ └── index.ts # Общий API модуля
└── catalog/ # Независимый доменный модуль
└── index.ts
2026-07-30 18:45:54 +03:00
```
2026-08-02 22:53:05 +03:00
Level 1 разрешает external calls, framework hooks, state и Auth scenarios внутри одной module boundary.
2026-07-30 18:45:54 +03:00
2026-07-30 21:44:47 +03:00
## Целевая форма Auth
2026-07-30 18:45:54 +03:00
```text
2026-07-30 21:44:47 +03:00
domains/
├── auth/ # Доменный пакет Level 2
│ ├── README.md
2026-08-02 22:53:05 +03:00
│ ├── api/ # Один SLM-модуль
2026-07-30 21:44:47 +03:00
│ │ ├── errors/
│ │ ├── factories/
2026-08-02 22:53:05 +03:00
│ │ ├── models/
│ │ ├── operations/
│ │ ├── ports/
│ │ ├── index.ts # Consumer-facing types
│ │ ├── ports.ts # Implementer-facing types
│ │ ├── factory.ts # Domain API factories
│ │ └── runtime.ts # Guards и public pure runtime
2026-07-30 21:44:47 +03:00
│ ├── adapters/ # Group
2026-08-02 22:53:05 +03:00
│ │ ├── identity-rest/ # SLM-модуль
│ │ ├── identity-realtime/ # SLM-модуль
2026-07-30 21:44:47 +03:00
│ │ └── request-session/ # SLM-модуль
│ ├── assemblies/ # Обязательная Group
2026-08-02 22:53:05 +03:00
│ │ ├── default/ # Штатный Auth graph
│ │ └── administration/ # Специальный trusted graph
2026-07-30 21:44:47 +03:00
│ └── react/ # Framework Group
2026-08-02 22:53:05 +03:00
│ ├── session/ # Provider готового API
│ ├── queries/ # Query/cache projection
│ └── login-form/ # Переиспользуемый domain UI
2026-07-30 21:44:47 +03:00
└── catalog/ # По-прежнему модуль Level 1
└── index.ts
2026-07-30 18:45:54 +03:00
```
2026-08-02 22:53:05 +03:00
Корневой `domains/auth/index.ts` удаляется. `catalog` и остальные домены не меняют форму только из-за перехода Auth.
2026-07-30 18:45:54 +03:00
## Перенос ответственности
2026-07-30 20:48:05 +03:00
| Исходная часть | Владелец Level 2 | Публичный путь |
|---|---|---|
2026-08-02 22:53:05 +03:00
| Session operations и public models | `auth/api` | `auth/api` |
| Port contracts и failures | `auth/api` | `auth/api/ports` |
| Runtime factories | `auth/api` | `auth/api/factory` |
| Error guards и public pure-функции | `auth/api` | `auth/api/runtime` |
| REST provider mapping | `auth/adapters/identity-rest` | Adapter API для assembly |
| Realtime protocol и correlation | `auth/adapters/identity-realtime` | Adapter API для assembly |
| Request cookies mapping | `auth/adapters/request-session` | Adapter API для assembly |
| Штатный production graph | `auth/assemblies/default` | `auth/assemblies/default` |
| Trusted administration graph | `auth/assemblies/administration` | `auth/assemblies/administration` |
2026-07-30 20:48:05 +03:00
| Provider и session hooks | `auth/react/session` | `auth/react/session` |
2026-08-02 22:53:05 +03:00
| Query/cache/hydration | `auth/react/queries` | `auth/react/queries` |
2026-07-30 20:48:05 +03:00
| Переиспользуемая форма | `auth/react/login-form` | `auth/react/login-form` |
| Страница, текст и redirect | `compositions` | API конкретной composition |
2026-07-30 18:45:54 +03:00
2026-08-02 22:53:05 +03:00
## Domain API и port
2026-07-30 18:45:54 +03:00
```ts
2026-08-02 22:53:05 +03:00
export type AuthSessionApi = {
getSession: () => Promise< AuthSession >
requestPhoneOtp: (
command: RequestPhoneOtpCommand,
) => Promise< RequestPhoneOtpOutcome >
verifyPhoneOtp: (
command: VerifyPhoneOtpCommand,
) => Promise< AuthSession >
}
```
```ts
export type AuthIdentityPort = {
requestPhoneOtp: (
command: AuthIdentityPortCommand,
) => Promise< AuthIdentityPortResult >
verifyPhoneOtp: (
command: VerifyIdentityPortCommand,
) => Promise< VerifyIdentityPortResult >
}
```
REST adapter реализует этот port поверх generated client. API проверяет records и преобразует port failures в `AuthError` .
## Штатная сборка
```ts
import {
createAuthSessionApi,
} from '@/domains/auth/api/factory '
2026-07-30 20:48:05 +03:00
2026-07-30 21:44:47 +03:00
import {
2026-08-02 22:53:05 +03:00
createIdentityRestAdapter,
} from '@/domains/auth/adapters/identity -rest'
export const createAuth = (): AuthGraph => ({
session: createAuthSessionApi({
identity: createIdentityRestAdapter(),
}),
})
```
2026-07-30 21:44:47 +03:00
2026-08-02 22:53:05 +03:00
Обычный production consumer использует:
```ts
2026-07-30 20:48:05 +03:00
import {
2026-08-02 22:53:05 +03:00
createAuth,
} from '@/domains/auth/assemblies/default '
2026-07-30 18:45:54 +03:00
```
2026-08-02 22:53:05 +03:00
Он не импортирует factory или adapter напрямую.
2026-07-30 18:45:54 +03:00
2026-08-02 22:53:05 +03:00
## Framework state
Старый `auth/stores` не переносится в `api` . React query/store projection принадлежит `auth/react/queries` :
2026-07-30 18:45:54 +03:00
```ts
2026-08-02 22:53:05 +03:00
export const useAuthSessionQuery = () => {
const api = useAuthApi()
2026-07-30 18:45:54 +03:00
2026-08-02 22:53:05 +03:00
return useQuery({
queryKey: ['auth', 'session'],
queryFn: api.getSession,
})
2026-07-30 18:45:54 +03:00
}
```
2026-08-02 22:53:05 +03:00
При Vue или другом framework та же модель и errors Domain API материализуются е г о собственными средствами.
## Realtime
`identity-realtime` скрывает socket protocol, operation IDs, acknowledgements и reconnect. Domain API возвращает обычный command outcome и публикует проверенные Auth events.
Если disconnect произошёл до acknowledgement, API не утверждает ложный отказ и может вернуть `AUTH_OPERATION_OUTCOME_UNKNOWN` . После gap binding получает `RESYNC_REQUIRED` и повторно вызывает `getSession()` .
## RSC
Server Component создаёт request-scoped Auth graph и передаёт Client Component только сериализуемый `AuthSession` или hydration payload. Client Component создаёт отдельный client graph; при SSR е г о render должен быть совместим с server prerender, а browser-only capabilities остаются в deferred effects.
`assemblies/default` используется в обоих местах только если её executable graph действительно совместим с о всеми declared conditions. Иначе появляется отдельная assembly, например `auth/assemblies/rsc` .
## Cross-domain graph
Если User package зависит от Auth, он импортирует только type contract:
2026-07-30 18:45:54 +03:00
```ts
2026-08-02 22:53:05 +03:00
import type {
AuthSessionApi,
} from '@/domains/auth/api '
2026-07-30 18:45:54 +03:00
```
2026-08-02 22:53:05 +03:00
User assembly принимает готовый API:
```ts
const auth = createAuth()
const user = createUser({
auth: auth.session,
})
```
2026-07-30 21:44:47 +03:00
2026-08-02 22:53:05 +03:00
User не импортирует Auth factory, port, adapter, assembly или React hooks. Если User остаётся модулем Level 1, е г о public API должен иметь явную точку передачи нужного Auth behavior.
2026-07-30 18:45:54 +03:00
## Порядок перехода
2026-08-02 22:53:05 +03:00
1. Зафиксировать consumers, external sources, state, errors и lifecycle исходного Auth module.
2. Объявить consumer-facing Domain API и public models.
3. Объявить dependency ports, records и closed failures.
4. Реализовать factory и проверить Domain API через fake ports.
5. Оформить каждую production implementation модулем `adapters/*` и добавить contract tests.
6. Создать `assemblies/default` для штатного production context.
7. Добавить специальные assemblies только для реально отличающихся graphs.
8. Перенести framework state, cache и hydration в modules Group `react` .
9. Перенести страницы, redirects и multi-domain UI в `compositions` .
10. Перевести внешние imports на разрешённые public paths.
11. Обновить dependency-connected graph owners и cross-domain inputs.
12. Удалить старый root `index.ts` Auth и объявить package checker-у .
Завершённость перехода определяется одной формой Auth и отсутствием обходных imports. Наличие других доменных модулей Level 1 не является миграционным долгом.