Перейти к основному содержимому

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/activeUser+активные опубликованные документы
GET/api/compliance/consent/statusUser+какие согласия ожидаются
POST/api/compliance/consentUser+принять активную версию документа
GET/api/compliance/exportUser+GDPR экспорт данных
POST/api/compliance/eraseUser+GDPR стирание своего аккаунта
POST/api/compliance/documentsOwnerсоздать черновик документа
POST/api/compliance/documents/{id}/publishOwnerопубликовать версию
GET/api/compliance/audit/verifyOwnerверифицировать аудит-хэш цепочку

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 экспорт возвращает данные пользователя в реальном браузере.