# Требования к ETL Fansy → fansy-store v1

## Подключение

- СУБД: PostgreSQL 16 / PostgreSQL Pro Certified (по согласованию).
- Хост, порт, имя БД, IP-allowlist — выдаются администратором ВМ
  Bridge-and-Join-s отдельно.
- Учётная запись: роль **`fansy_etl`** (создаётся миграцией
  `000__roles.sql`). Пароль выдаётся через защищённый канал, не в
  репозиторий.
- TLS: обязательно (`sslmode=verify-full` со стороны клиента ETL).

## Куда писать

- Только в схему `fansy_staging`. Прав на DDL нет, на схему `fansy`
  тоже нет. INSERT/UPDATE/SELECT на таблицы staging.
- Запись в `fansy.*` происходит на нашей стороне после валидации.

## Тип load

- **Инкрементный UPSERT** в staging по PK (`id`):
  ```sql
  INSERT INTO fansy_staging.clients (id, ...) VALUES (...)
  ON CONFLICT (id) DO UPDATE SET ..., loaded_at = now();
  ```
- Справочники с относительно небольшим размером и редкой сменой
  (`securities`, `participants`) разрешена **полная перезаливка** не
  чаще одного раза в сутки. Полная перезаливка реализуется через
  транзакцию: `TRUNCATE` + `COPY` + `COMMIT`.

## SLA на свежесть данных

| Таблица | SLA свежести |
|---|---|
| `portfolios` | ≤ 1 минута после фактического изменения в Fansy |
| `clients`, `depo_accounts`, `client_documents`, `iia_contracts` | ≤ 5 минут |
| `securities`, `participants`, `settlement_requisites` | ≤ 24 часа (по событию или по расписанию) |

## Форматы и кодировки

- Все timestamp — `timestamptz` в **UTC** (явная зона `+00`).
- Все строковые поля — UTF-8.
- ИНН, коды депонентов, ISIN, SecurityCode — в верхнем регистре.
- Числа с дробной частью (`numeric(38,16)`) — точка как разделитель,
  без разделителей тысяч.

## Обработка ошибок

При нарушении CHECK-ограничений, FK или типов команда Fansy:

1. Пишет запись в `fansy_staging.etl_errors`:
   ```sql
   INSERT INTO fansy_staging.etl_errors (source_table, source_pk, payload, error_message)
   VALUES ('fansy.position', '<pk>', '<json>', '<text>');
   ```
2. Логирует у себя и продолжает работу.
3. Не блокирует загрузку остальных записей.

Мы (Bridge-and-Join-s) еженедельно просматриваем `etl_errors`,
поднимаем инциденты с командой Fansy.

## Окна и расписание

- Регламентное окно простоя — **с 23:00 до 23:30 МСК**, по средам.
  В это время ETL может приостанавливаться для обновлений.
- Внеплановые работы — анонсируются за 2 часа в общем чате.

## Конфиденциальность

- ПДн (ФИО, документ, дата рождения) — только по нужным таблицам.
- Журналирование SQL-запросов ETL **не должно** включать значения ПДн.
- Соединения только с IP-allowlist'а.

## Контроль и наблюдаемость

Мы предоставим команде Fansy `read-only` доступ к двум представлениям:

- `fansy_staging.v_load_lag` — задержка свежести по таблицам.
- `fansy_staging.v_load_stats` — счётчики INSERT/UPDATE за сутки.

(Создаются в более позднем PR — `M3`.)

## Точка контакта

- Технический контакт со стороны Bridge-and-Join-s — указан в
  `docs/architecture/plan.md`, раздел «Контакты».
- Эскалация — в общий канал интеграции, тред «fansy-store ETL».
