Legal & compliance
Розничная FX/CFD/crypto-брокерия несёт юридические обязанности и ведение записей. Модуль реализует четыре отраслевых столпа: согласие на раскрытие рисков, tamper-evident аудит-трейл, MiFID/ESMA-style ведение записей, GDPR. Всё управляется флагом фичи Compliance.
1. Версионированные юридические документы + согласие
LegalDocument(агрегат) — версионированные Условия использования, CFD Раскрытие рисков или Политика конфиденциальности. Версия создаётся, затем публикуется; опубликованные версии неизменяемы (редактирование выбрасывает), поэтому точный текст, с которым пользователь согласился, всегда восстановим. Активный документ типа = его наивысшая опубликованная версия.ConsentRecord(агрегат) — неизменяемая запись согласия пользователя с конкретной версией документа в определённое время, с исходным IP.- Enforcement:
RouteGroupBuilder/RouteHandlerBuilder.RequireConsent(type)блокирует действие с403когда опубликованный документ этого типа существует и пользователь не дал согласие на его активную версию. Применяется к созданию копи-профиля (RiskDisclosure). Ничего не опубликовано → действия разрешены — нечего подтверждать — поэтому включение модуля ничего не блокирует ретроактивно, пока раскрытие фактически не опубликовано.
2. Tamper-evident аудит-трейл
AuditLog записи объединены в хэш-цепочку: каждая строка хранит PrevHash и Hash = SHA-256(prev | каноничные поля).
AuditChainInterceptor применяет цепочку прозрачно при SaveChanges, поэтому существующие места вызова аудита не изменены.
IAuditTrailVerifier.VerifyAsync заново проходит цепочку, сообщает о первой строке, чей сохранённый хэш или обратная ссылка
больше не совпадают — обнаруживает любое изменение или удаление прошлой записи. Owner-эндпоинт: GET /api/compliance/audit/verify.
3. Ведение записей (MiFID II / ESMA RTS)
Ведение записей обеспечивается неизменяемым, хэш-цепочечным аудит-логом плюс сохранёнными записями согласия и
soft-deleted (никогда не hard-deleted) доменными записями. UTC-временные метки из инъектированного TimeProvider. Записи согласия
хранят версию документа + IP; опубликованные юридические документы никогда не мутируются. Хранение = непurgerи этих
таблиц (append-only / soft-delete).
4. GDPR data rights
GET /api/compliance/export— машиночитаемый экспорт данных вызывающего (профиль, согласия, копи-профили, prop-firm чеелленджи).POST /api/compliance/erase— право на стирание:AppUser.Anonymize()удаляет PII (email, MFA) и строка soft-delete'ится, сохраняя ссылочную/аудитную целостность.
Сводка API
| Метод | Маршрут | Роль | Назначение |
|---|---|---|---|
| GET | /api/compliance/documents/active | User+ | активные опубликованные документы |
| GET | /api/compliance/consent/status | User+ | какие согласия ожидаются |
| POST | /api/compliance/consent | User+ | принять активную версию документа |
| GET | /api/compliance/export | User+ | GDPR экспорт данных |
| POST | /api/compliance/erase | User+ | GDPR стирание своего аккаунта |
| POST | /api/compliance/documents | Owner | создать черновик документа |
| POST | /api/compliance/documents/{id}/publish | Owner | опубликовать версию |
| GET | /api/compliance/audit/verify | Owner | верифицировать аудит-хэш цепочку |
UI: /settings/legal (nav Settings → Legal & Privacy, под флагом Compliance) показывает ожидающие соглашения с кнопками принятия + действия GDPR export/erase.
Тесты
- Unit —
UnitTests/Compliance/LegalDocumentTests.cs(черновик/публикация/неизменяемость, захват согласия),AuditChainTests.cs(хэш-ссылки, обнаружение подделки, чувствительность содержимого). - Integration —
IntegrationTests/CompliancePersistenceTests.cs(активная версия + запросы согласия на реальном Postgres),AuditChainIntegrityTests.cs(цепочка верифицируется нетронутой, затем обнаруживает SQL-level подделку),ComplianceFlowTests.cs(WebApplicationFactory, изолированная БД: согласие блокирует создание копи до принятия раскрытия рисков; GDPR экспорт; верификация аудита). - E2E —
E2ETests/ComplianceTests.cs: страница Legal & Privacy рендерится и GDPR экспорт возвращает данные пользователя в реальном браузере.