Andrey Epifancev 7a35b79d5e docs: change slice-0-skeleton под факты платформы — NATS без JetStream, Python 3.11, без CI и Nexus
Обмен с ядром на core NATS: подписка queue group, ack status=processing сразу по получении, process-local
LRU job_id против повторных запросов, публикация результата с повторами; удалены durable consumer / max_deliver /
ack_wait. Dockerfile python:3.11-slim; make check / make check-full вместо CI; raisa_* фильтруются при
dev-установке. Обновлены proposal, design (решения без обсуждения), specs, tasks, CLAUDE.md, openspec/config.yaml.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-03 16:21:45 +04:00

65 lines
6.1 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 — скелет tabular-parser
**Срез:** 0 «Скелет» (`../docs/context/09-delivery-plan.md`). **Репозиторий:** tabular-parser. **Issue:** RSHB/arm-tabular-parser#1.
**Родительский change:** `../docs/openspec/changes/slice-0-skeleton` (контракт v1.0, compose, проверки качества).
**Соседние:** `../arm-core/openspec/changes/slice-0-skeleton`, `../scan-gateway/openspec/changes/slice-0-skeleton`.
## Why
Репозиторий сейчас — полная копия каркаса `arm-core` с фронтом, Alembic и моделями, то есть противоречит DECISION-4
(сервис без БД, видит только NATS и S3). Прежде чем в Срезе 2 писать парсер ОСВ, нужен сервис, который уже умеет
принять запрос из NATS, подтвердить его, прочитать файл из S3, положить результат и ответить по контракту v1.0 — чтобы
парсер стал чистой функцией «байты → документы», а транспорт был проверен end-to-end вместе с ядром на той платформе,
что есть: NATS без JetStream, Python 3.11, без Nexus.
## What Changes
- **Вырезать из шаблона** (список — `CLAUDE.md`, «Соглашения шаблона»): `web/`, `setup/.npmrc` и npm-шаги
`setup/setup.sh`; из `app.py` — mount SPA, CORS, SMB-сессия, импорт `raisa_fastapi_protected_api`; `db/`, `models/`,
`repositories/`, `alembic/`, `alembic.ini`; настройки `OPENBAO.DATABASE`, `OPENBAO.SMB`; зависимости `asyncpg`,
`SQLAlchemy`, `alembic`, `smbprotocol`, `argon2-cffi`, `raisa_fastapi_protected_api`; шаблонный `README.md`.
- **Инструменты**: `api/pyproject.toml` (ruff, mypy), `requirements-dev.txt` = `-r requirements.txt` + инструменты,
`Dockerfile` (`python:3.11-slim`; строка убрана из `.gitignore`), `Makefile` с общими целями `up / test /
test-integration / lint / check / check-full` + `venv`, `.env.example`, `.env.test`; `Settings` читает `ENV_FILE`;
`SERVICE_NAME = "tabular-parser"`.
- **Контракт**: вендоренные схемы `api/contracts/` + pydantic-модели `src/contract/` (запрос, конверт со статусами
`processing | done | needs_check | error`, файл результата); тест идентичности с `../docs/contracts`.
- **Воркер** `src/core/worker.py` (NATS без JetStream): подписка на `recognition.tabular.request` в queue group
`tabular-parser`; по получении — сразу ack: конверт `status = processing` в `recognition.result`
(`Nats-Msg-Id = ack:<job_id>:<attempt>`); затем чтение исходника из S3 `uploads/…`, вызов парсера, запись
`results/{file_id}/{job_id}/result.json`, публикация конверта результата (`Nats-Msg-Id = result:<job_id>:<attempt>`).
Process-local множество `job_id` в работе: повторный запрос (ядро публикует повторно, не получив ack) получает ack и не
обрабатывается второй раз.
- **Парсер как интерфейс**: `src/parser/` — протокол `Parser` и `NullParser`, возвращающий `status = error`,
`error.code = NOT_IMPLEMENTED` для любого файла (Срез 2 заменяет реализацией §1/§12); `api/rules/README.md` —
место словарей синонимов.
- **Ошибки транспорта** всегда превращаются в результат: запрос не по схеме → `SCHEMA_MISMATCH`; файл не читается из
S3 → `FILE_READ_ERROR`; неожиданное исключение → `UNKNOWN_ERROR`. Ядро не ждёт таймаута, если сервис жив.
- **Healthcheck** `/healthcheck` шаблона дополняется полем `nats` (`ok`/`down`).
- **Проверки качества** вместо CI: `make check` (ruff, mypy, pytest без Docker, идентичность контракта) и
`make check-full` (+ интеграционный тест против compose, `docker build`) — по `../docs/dev/checks.md`.
## Capabilities
### New Capabilities
- `tabular-recognition-service`: stateless-сервис, который принимает задания из NATS без JetStream, подтверждает их,
обменивается файлами через S3 и отвечает по контракту v1.0; в Срезе 0 — с парсером-заглушкой.
### Modified Capabilities
<!-- openspec/specs пуст -->
## Impact
- **Таблицы DBML:** сервис не пишет в БД. Косвенно: `recognition_job` ядра получает `status = processing`
(`started_at`), затем `error`, `error_code = NOT_IMPLEMENTED`, `service_name = tabular-parser` из конвертов.
- **Правила:** §1.0/§12 — только как контракт будущего парсера (интерфейс `Parser`), §9.4 — статусы задания.
- **Зависимости:** удаляются БД/SMB/фронт; добавляются `ruff`, `mypy`, `pytest*`, `jsonschema` (валидация примеров).
- **Внешние системы:** NATS без JetStream (subjects `recognition.*`), MinIO/S3 (бакет `arm-ka`).
## Non-goals
- Разбор ОСВ и форм ББ/ОФР (§1, §12) — Срез 2; property-тесты на `../fixtures/osv/**` — Срез 2.
- Словари `rules/*.yaml` — Срез 2 (здесь только каталог и README).
- Периодический heartbeat `processing` — не реализуется (один ack при получении).
- Любая работа с БД, SMB, фронтом; конфигурации CI.