- Add bible.git as submodule at bible/ - Rename bible/ → bible-local/ (project-specific architecture) - Update CLAUDE.md to reference both bible/ and bible-local/ - Add AGENTS.md for Codex with same structure Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.7 KiB
5.7 KiB
Реализация JSON hardware-ingest по INTEGRATION_GUIDE.md
Summary
Добавляем новый инструмент импорта hardware snapshot: POST /ingest/hardware + форму в ingest UI, без ломки текущего POST /ingest/logbundle.
Импорт должен:
- находить/создавать
assetпоhardware.board.serial_number, - автоматически назначать новые asset в служебный customer/project (
Без заказчика/Без проекта), - создавать/обновлять компоненты + LOT,
- писать
observationsсdetails JSON, - синхронизировать
installations, - генерировать timeline events (
LOG_COLLECTED,INSTALLED,REMOVED,FIRMWARE_CHANGED,COMPONENT_WARNING,COMPONENT_FAILED), - создавать
failure_eventsприCritical.
Подтвержденные решения
- Scope:
API + UI. - Endpoint: основной
POST /ingest/hardware. - Новые asset по умолчанию идут в служебный customer/project:
- customer:
Без заказчика - project:
Без проекта
- customer:
- Статусы:
Critical->failure_event+COMPONENT_FAILEDWarning->COMPONENT_WARNING
- Расширенные observation-поля храним в
observations.details JSON. - Ответ endpoint: как в guide (
status,bundle_id,asset_id,collected_at,duplicate,summary|message).
Публичные API / контракты
- Новый маршрут в
internal/api/ingest.go:POST /ingest/hardware
- Request JSON:
collected_at(required, RFC3339)target_host(required)hardware(required) сboard.serial_number(required)- опционально:
filename,source_type,protocol, секцииcpus/memory/storage/pcie_devices/power_supplies/firmware
- Response success (201):
status: "success"bundle_id,asset_id,collected_at,duplicate: falsesummaryс детализированными счетчиками
- Response duplicate (200):
- те же поля +
duplicate: true,message
- те же поля +
- Validation error (400):
status: "error",error: "validation_failed",details.field,details.message
Изменения по файлам (implementation design)
migrations/0007_hardware_ingest/up.sqlиdown.sqlALTER TABLE observations ADD COLUMN details JSON NULL;
internal/api/ingest.go- новый handler
handleHardware - строгая decode/validate
- вызов
IngestHardware(...)
- новый handler
internal/ingest/service.goHardwareInput,HardwareResult, summary counters- transactional pipeline
ensureServiceProject():- customer
Без заказчика(create if missing) - project
Без проекта(create if missing)
- customer
ensureAssetByBoardSerial():- lookup по
assets.vendor_serial = board.serial_number - create если нет (
name=target_host,project_id=service_project_id,vendor/modelпо board) - update vendor/model при валидных значениях
- lookup по
internal/ingest/parser_hardware.go- parse + normalize + flatten snapshot
- генерация serial:
- CPU:
{board_serial}-CPU-{socket} - PCIe:
{board_serial}-PCIE-{slot}если пусто/N/A
- CPU:
- фильтрация
present=false,status=Empty
internal/ingest/lot_classifier.go- LOT rules для CPU/DIMM/Storage/PSU/PCIe
ensureLotByCode()
internal/ingest/service.go(status/failure/events)observations.detailsхранит:component_type,slot,status,present,telemetry, raw attrsCritical:COMPONENT_FAILEDв timelinefailure_events(source=hardware_ingest, deterministicexternal_id)
Warning:COMPONENT_WARNINGв timeline
- system firmware (
hardware.firmware):- сравнение с последним значением и
FIRMWARE_CHANGEDдля asset
- сравнение с последним значением и
- UI:
internal/api/ui_ingest.tmplinternal/api/ui.go- добавить секцию “Hardware Ingest” с примером payload на основе
bible/docs/import-example-full.json
Идемпотентность
- Хеш считается от канонически marshaled hardware request.
- Если hash уже есть:
- без side effects
200 duplicate=true
- Если hash новый:
- полный pipeline
201
Тесты и acceptance
TestIngestHardwareIdempotent: 201 -> 200 duplicate, без дублей вlog_bundles/observations/installations.- Тест авто-создания служебного customer/project и auto-create asset.
- Тест замены компонента:
REMOVED+INSTALLED. - Тест firmware change:
FIRMWARE_CHANGED. - Тест статусов:
- Warning ->
COMPONENT_WARNING - Critical ->
COMPONENT_FAILED+failure_events
- Warning ->
- Validation tests:
- missing required fields
- invalid RFC3339
- unknown field -> 400
- UI smoke:
/ui/ingestсодержит форму hardware ingest.
Assumptions and defaults
- Служебные записи:
- customer.name =
Без заказчика - project.name =
Без проекта
- customer.name =
- При дублях по имени используется запись с минимальным
id. manufacturer/product_name == "NULL"->NULLв БД.- Новые
event_type(COMPONENT_WARNING,COMPONENT_FAILED) хранятся как строки без enum-миграции. /ingest/logbundleостается полностью совместимым.