Andrey Epifancev f12ce87346 docs: соглашения шаблона в CLAUDE.md и OpenSpec change slice-0-skeleton
Срез 0 (issue #1): раздел «Соглашения шаблона» (что оставлено от шаблона команды, что
вырезается, что добавляется); change openspec/changes/slice-0-skeleton — proposal, design
с таблицей «Decisions made without discussion», спеки и tasks; в openspec/config.yaml
строки с двоеточием взяты в кавычки (YAML разбирал их как словари).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 02:43:34 +04:00

79 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Proposal: Срез 0 — скелет ядра arm-core
**Срез:** 0 «Скелет» (`../docs/context/09-delivery-plan.md`). **Репозиторий:** arm-core. **Issue:** RSHB/arm-core#1.
**Родительский change:** `../docs/openspec/changes/slice-0-skeleton` (контракт v1.0, compose, CI-шаблон).
**Соседние:** `../tabular-parser/openspec/changes/slice-0-skeleton`, `../scan-gateway/openspec/changes/slice-0-skeleton`.
## Why
Ядро — единственный писатель в PostgreSQL и единственная точка обмена с сервисами распознавания. Пока нет схемы БД по
DBML v5.13, прав как данных и работающего outbox/inbox, ни один следующий срез (справочники, загрузка файлов, парсер)
не может начаться: каждому нужны таблицы, пользователь с правами и канал в NATS. Срез 0 делает всё это один раз,
без бизнес-логики, и доказывает end-to-end тестом на пустых обработчиках.
## What Changes
- **Инструменты шаблона**: `api/pyproject.toml` (ruff — формат, совместимый с black, и lint; mypy), `requirements-dev.txt`
переписан как `-r requirements.txt` + dev-инструменты (пины шаблона были рассинхронизированы), `Dockerfile` в корне
(строка `Dockerfile` убрана из `.gitignore`), `Makefile` с целями `up / migrate / test / lint / seed`, `.env.example`,
`.env.test`; `Settings` читает путь к env-файлу из `ENV_FILE` (шаблонный `pytest.ini` уже задаёт его, но `config.py` игнорировал).
- **Модель данных**: ORM 1:1 с `../docs/model/data-model-v5.13.dbml` — 43 таблицы, 27 enum'ов, все FK, уникальные и
частичные индексы (`related_group_member` WHERE is_current, `consolidation_lock` WHERE released_at IS NULL,
`document` NULLS NOT DISTINCT), схема `dkb`. Миграция `0001_dbml_v5_13` создаёт всё с нуля и полностью откатывается.
`api/scripts/check_dbml_vs_orm.py` сравнивает DBML и ORM-метаданные; расхождение — ошибка CI.
- **Seed** (`api/seed/`, идемпотентный `python -m scripts.seed`): `regional_office` (ГО), `role` (7 ролей ТЗ 8.1),
`permission` (16 сочетаний объект × действие из §10), `role_permission` по §10 (ASSUMPTION(OQ-16)),
`chart_of_account` (План счетов 94н + субсчета типовой 1С, упомянутые в §4/§6), `elimination_rule` v1 для ББ (§4, 8 правил)
с `elimination_rule_account`, `required_document_rule` для BASIC и EXTENDED (ASSUMPTION(OQ-46)); `--dev`: примеры РФ и
по одному `app_user` на роль.
- **Аутентификация и права**: `core/auth.py` — проверка JWT (`TokenVerifier`: dev HS256-эмитент за флагом
`AUTH_DEV_ISSUER`; каркас `RaisaVerifier` под JWKS/публичный ключ, параметры — вопрос к человеку), поиск `app_user`
по email, зависимости `current_user` и `require(permission_code)`, `GET /api/v1/me`, `POST /api/v1/dev/token`
(только при включённом флаге). Policy-слой (филиал/ЗО/статус) — не здесь (Срез 1+).
- **Обмен через `recognition_job`** (DECISION-4): вендоренные схемы контракта `api/contracts/` + pydantic-модели
`src/contract/`; outbox-паблишер (`queued` → NATS → `published`, `Nats-Msg-Id = <job_id>:<attempt>`), durable
consumer `recognition.result` (дедуп по `result_msg_id`, обновление статуса/метрик, регистрация файла результата в
`s3_object`, `dlq` после `max_deliver`), вахтёр `reply_deadline` → `timeout`. Маппинг документов — точка расширения,
реализуется в Срезе 2.
- **Аудит**: `services/audit.py` — единственный способ записать `audit_event` (append-only, `before/after` jsonb).
- **CI**: `.gitea/workflows/ci.yml` из шаблона docs: ruff, mypy, pytest на PostgreSQL/NATS/MinIO, миграции
upgrade → downgrade → upgrade, `check_dbml_vs_orm`, сборка образа; job `web`: biome, tsc, rsbuild build.
- **Документация репозитория**: `README.md` заменяется описанием сервиса (команды, env, как поднять), `CLAUDE.md` —
раздел «Соглашения шаблона» (уже в ветке).
## Capabilities
### New Capabilities
- `data-model`: схема БД = DBML v5.13; миграции применяются с нуля и откатываются; сверка ORM ↔ DBML.
- `reference-data-seed`: идемпотентная загрузка справочников продукта (роли, права, матрица, план счетов, правила
элиминации, чек-лист) и dev-данных.
- `authn-authz`: вход по JWT, пользователь по email, эффективные права, зависимость `require(permission)`, `/api/v1/me`.
- `recognition-job-exchange`: outbox/inbox через `recognition_job`, идемпотентность, таймауты, DLQ, регистрация результата в `s3_object`.
- `audit-trail`: append-only запись событий `audit_event` через единый сервис.
### Modified Capabilities
<!-- openspec/specs пуст -->
## Impact
- **Таблицы DBML v5.13:** все 43 (ORM и миграция); данными заполняются `regional_office`, `role`, `permission`,
`role_permission`, `chart_of_account`, `elimination_rule`, `elimination_rule_account`, `required_document_rule`,
`app_user` (dev), `user_role` (dev); в рантайме Среза 0 изменяются `recognition_job`, `s3_object`, `audit_event`.
Новых полей и таблиц нет.
- **Параграфы правил:** §4 (seed правил элиминации), §9.4 (жизненный цикл `recognition_status`), §10 (матрица прав).
- **Зависимости (новые):** `PyJWT[crypto]`, `pydbml` (dev, сверка DBML), `ruff`, `mypy`, `pytest-cov`, `types-*`;
`nats-py` уже есть (JetStream API), `miniopy-async` уже есть.
- **Внешние системы:** NATS JetStream (stream `RECOGNITION`), MinIO/S3 (бакет `arm-ka`), PostgreSQL 15 (`CREATE SCHEMA dkb`,
`CREATE TYPE`).
- **Фронт:** без изменений кода; добавляется только CI-job.
## Non-goals
- Загрузка файлов, `stored_file`/`document` жизненный цикл и маппинг результата в `osv_entry`/`financial_statement_*` (Срез 2).
- CRUD справочников и экраны администратора (Срез 1); policy-слой по филиалу/ЗО/статусу (Срез 1+).
- Реальная проверка JWT РАИСА (нужны параметры — Open Questions родительского change'а); в Срезе 0 — только dev-эмитент
и конфигурируемый каркас.
- Авто-элиминация ОФР (OQ-09) — правила ОФР в seed не входят.
- Полный план счетов конкретного клиента — только стандартный 94н + типовые субсчета 1С; остальное добавляет администратор (ARCH-004).
- Любые экраны фронта.