Andrey Epifancev 6bb111db38 chore(openspec): архив change slice-0-skeleton
Срез 0 реализован и влит (PR #3), change перенесён в openspec/changes/archive, спеки — в openspec/specs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-04 19:44:42 +04:00

67 lines
6.2 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`
(если читаемы `job_id`, `file_id`, `attempt`, иначе — лог ошибки без ответа); файл не читается из
S3 → `FILE_READ_ERROR`; неожиданное исключение → `UNKNOWN_ERROR`. Ядро не ждёт таймаута, если сервис жив.
- **Healthcheck** `/healthcheck` шаблона дополняется полем `nats` (`ok`/`down`; `off` — NATS выключен флагом
`NATS_ENABLED=false`).
- **Проверки качества** вместо 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.