Some checks are pending
ci / verify (push) Waiting to run
Приёмка второго круга: Grok принят, у Codex форматирование по-прежнему несёт исправление синхронизации Antigravity, у Antigravity два интеграционных теста красные на реальной базе и две ветки конфликтуют между собой. Задания третьего круга фиксируют, что именно доделать и в каком порядке вливать, плюс перевод пилота с арендатора-заглушки на настоящего. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
80 lines
8.8 KiB
Markdown
80 lines
8.8 KiB
Markdown
# Задание для Codex, круг 2: исправить ветку форматирования, перевести пилот на настоящего арендатора
|
||
|
||
- Репозиторий: https://git.ochenstarik.ru/ochenstarik/krona-staff
|
||
- Основа: `codex/bootstrap-platform-foundation` (`f5ac179`)
|
||
- Итоги приёмки: `docs/audit/2026-09-26/ACCEPTANCE-2.md`. Основное задание `TASK-CODEX.md` остаётся в силе, этот файл его дополняет.
|
||
|
||
## 1. Пересобрать ветку форматирования (сегодня)
|
||
|
||
По данным приёмки, коммит `fd1ec3d` в ветке `codex/fix-format-baseline` содержит, кроме форматирования, функциональное изменение Antigravity. После нормализации prettier файлы `src/domain/sync/service.ts` и `tests/unit/sync.test.ts` совпадают с его исправлением S1. Это одновременно смешение тем и правка чужой зоны (AGENTS.md). Кроме того, при влитии обеих веток изменение придёт дважды.
|
||
|
||
**Что сделать:** пересобрать коммит форматирования от `f5ac179` так, чтобы в нём было только `prettier --write`, без изменений в `src/domain/sync/**` и `tests/unit/sync.test.ts`. Исправление S1 должно приходить только из ветки Antigravity. Затем перебазировать `codex/fix-live-database` на новый коммит форматирования.
|
||
|
||
**Готово, когда:**
|
||
|
||
- `git diff <новый коммит>~1 <новый коммит> -w` после `prettier --check` не содержит изменений поведения;
|
||
- стенд Grok на `codex/fix-live-database` даёт K3/N2 и K4/N1 зелёными, а K13/SYNC-A и K13/SYNC-B — красными (они придут от Antigravity).
|
||
|
||
## 2. Пилот — на настоящего арендатора
|
||
|
||
По данным сессии «БП» (запросы только на чтение к `krona-staff-pilot-postgres-1`), под заглушкой `01J00000000000000000000000` сейчас лежит:
|
||
|
||
| Таблица | Строк |
|
||
| ---------------------- | ----- |
|
||
| `staff_employees` | 51 |
|
||
| `staff_payroll_ledger` | 3 830 |
|
||
| `staff_work_items` | 3 353 |
|
||
| `staff_daily_metrics` | 2 894 |
|
||
| `staff_audit_log` | 49 |
|
||
|
||
Остальные таблицы — единицы строк.
|
||
|
||
Настоящий арендатор владельца в платформе — `01M2R6AC5652NPT3MG34DKN4ZP` («Сушигедза»).
|
||
|
||
### 2.1 Чтобы заглушка не вернулась
|
||
|
||
| Где | Что сделать |
|
||
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||
| `deploy/pilot/setup.sh:20` | Не генерировать `STANDALONE_TENANT_ID` со значением-заглушкой: требовать его явно, без значения по умолчанию, с понятной ошибкой |
|
||
| `compose.yaml:16` | `${STANDALONE_TENANT_ID:?…}` вместо `${STANDALONE_TENANT_ID:-01J000…}` |
|
||
| `.env.example:14` | Оставить пустым с комментарием, откуда берётся значение (идентификатор организации в платформе) |
|
||
| `src/config.ts` | Вне режима разработки на loopback отклонять `01J00000000000000000000000` при старте как известную заглушку |
|
||
|
||
### 2.2 Перенос уже внесённых данных
|
||
|
||
Способ выбираешь сам: однократная перезапись `tenant_id` или переимпорт книги владельца. В обоих случаях обязательно:
|
||
|
||
1. **Сначала резервная копия** (задача K18 из основного задания) и проверка, что из неё действительно можно восстановиться. Без этого перенос не начинать.
|
||
2. **Сначала прогон на копии** пилотной базы, затем на пилоте в согласованное окно, при остановленном приложении. Терминалы на это время копят отметки у себя.
|
||
3. **Перезапись выполняет привилегированная роль администратора БД**, а не роль приложения. RLS с `FORCE`, составные внешние ключи `(tenant_id, id)`, неизменяемые журналы (`staff_payroll_ledger`, `staff_audit_log`) — всё это нужно учесть явно: одна транзакция, внешние ключи переустанавливаются в ней же, триггеры неизменяемости отключаются только внутри неё.
|
||
4. **Скрипт в репозитории:** `scripts/rehome-tenant.mjs` (или аналог) с режимом `--dry-run` (только отчёт о количестве строк по таблицам) и отказом работать, если целевой арендатор уже содержит данные.
|
||
5. **Запись о переносе** в `staff_audit_log` нового арендатора: кто, когда, откуда, куда, сколько строк.
|
||
|
||
**Готово, когда:**
|
||
|
||
- `SELECT DISTINCT tenant_id` по всем таблицам со столбцом `tenant_id` возвращает только `01M2R6AC5652NPT3MG34DKN4ZP`;
|
||
- количество строк в каждой таблице до и после совпадает;
|
||
- сумма `amount_minor` в реестре начислений до и после совпадает;
|
||
- пилот под новым арендатором показывает тех же 51 сотрудника;
|
||
- тест изоляции арендаторов зелёный.
|
||
|
||
Вывод `--dry-run` и итоговые запросы приложи к отчёту. Grok проверит скрипт на копии: данные под старым арендатором → перенос → сверка.
|
||
|
||
### 2.3 Скрипт сопоставления с платформой
|
||
|
||
`docs/PLATFORM-INTEGRATION.md` обещает сопоставление standalone ULID с записями Core, но скрипта нет. После пункта 2.2 перенос арендатора уже решён, поэтому скрипт сводится к заполнению `core_user_id` у сотрудников:
|
||
|
||
- вход — выгрузка пользователей платформы (JSON или CSV: идентификатор пользователя Core и признак сопоставления — табельный номер, e-mail или телефон);
|
||
- режим `--dry-run` с отчётом: сопоставлены, не найдены, найдены неоднозначно;
|
||
- идемпотентность: повторный запуск ничего не меняет, существующие `core_user_id` не перезаписываются без флага;
|
||
- запись в журнал аудита.
|
||
|
||
**Готово, когда** скрипт есть, покрыт тестом на реальной PostgreSQL и описан в `docs/PLATFORM-INTEGRATION.md`.
|
||
|
||
## 3. Не делать
|
||
|
||
**Не менять `PlatformIdentityAdapter` под нынешние неподписанные заголовки `x-tenant-id`**, которые платформа передаёт модулю. Договор будет с подписью: пункты А-5, С-6, С-7 плана платформы. Им занимается сессия «БП» в репозитории `business-platform`. Режим `platform` остаётся недоступным, пока платформа этого не сделает.
|
||
|
||
## Порядок
|
||
|
||
Пункт 1 → пункт 2.1 → резервная копия (K18) → пункт 2.2 на копии → 2.2 на пилоте → пункт 2.3. Параллельно продолжается основное задание: этап 2 — доступ и пилот, этап 3 — деньги (K5 и K6 теперь воспроизводятся по существу).
|