Files
core/bible-local/docs/plan/Plan #1.md
Michael Chus c5d253a9df Add shared bible submodule, rename local bible to bible-local
- 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>
2026-03-01 16:37:10 +03:00

5.7 KiB
Raw Blame History

Реализация JSON hardware-ingest по INTEGRATION_GUIDE.md

Summary

Добавляем новый инструмент импорта hardware snapshot: POST /ingest/hardware + форму в ingest UI, без ломки текущего POST /ingest/logbundle.

Импорт должен:

  1. находить/создавать asset по hardware.board.serial_number,
  2. автоматически назначать новые asset в служебный customer/project (Без заказчика / Без проекта),
  3. создавать/обновлять компоненты + LOT,
  4. писать observations с details JSON,
  5. синхронизировать installations,
  6. генерировать timeline events (LOG_COLLECTED, INSTALLED, REMOVED, FIRMWARE_CHANGED, COMPONENT_WARNING, COMPONENT_FAILED),
  7. создавать failure_events при Critical.

Подтвержденные решения

  1. Scope: API + UI.
  2. Endpoint: основной POST /ingest/hardware.
  3. Новые asset по умолчанию идут в служебный customer/project:
    • customer: Без заказчика
    • project: Без проекта
  4. Статусы:
    • Critical -> failure_event + COMPONENT_FAILED
    • Warning -> COMPONENT_WARNING
  5. Расширенные observation-поля храним в observations.details JSON.
  6. Ответ endpoint: как в guide (status, bundle_id, asset_id, collected_at, duplicate, summary|message).

Публичные API / контракты

  1. Новый маршрут в internal/api/ingest.go:
    • POST /ingest/hardware
  2. 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
  3. Response success (201):
    • status: "success"
    • bundle_id, asset_id, collected_at, duplicate: false
    • summary с детализированными счетчиками
  4. Response duplicate (200):
    • те же поля + duplicate: true, message
  5. Validation error (400):
    • status: "error", error: "validation_failed", details.field, details.message

Изменения по файлам (implementation design)

  1. migrations/0007_hardware_ingest/up.sql и down.sql
    • ALTER TABLE observations ADD COLUMN details JSON NULL;
  2. internal/api/ingest.go
    • новый handler handleHardware
    • строгая decode/validate
    • вызов IngestHardware(...)
  3. internal/ingest/service.go
    • HardwareInput, HardwareResult, summary counters
    • transactional pipeline
    • ensureServiceProject():
      • customer Без заказчика (create if missing)
      • project Без проекта (create if missing)
    • ensureAssetByBoardSerial():
      • lookup по assets.vendor_serial = board.serial_number
      • create если нет (name=target_host, project_id=service_project_id, vendor/model по board)
      • update vendor/model при валидных значениях
  4. internal/ingest/parser_hardware.go
    • parse + normalize + flatten snapshot
    • генерация serial:
      • CPU: {board_serial}-CPU-{socket}
      • PCIe: {board_serial}-PCIE-{slot} если пусто/N/A
    • фильтрация present=false, status=Empty
  5. internal/ingest/lot_classifier.go
    • LOT rules для CPU/DIMM/Storage/PSU/PCIe
    • ensureLotByCode()
  6. internal/ingest/service.go (status/failure/events)
    • observations.details хранит: component_type, slot, status, present, telemetry, raw attrs
    • Critical:
      • COMPONENT_FAILED в timeline
      • failure_events (source=hardware_ingest, deterministic external_id)
    • Warning:
      • COMPONENT_WARNING в timeline
    • system firmware (hardware.firmware):
      • сравнение с последним значением и FIRMWARE_CHANGED для asset
  7. UI:
    • internal/api/ui_ingest.tmpl
    • internal/api/ui.go
    • добавить секцию “Hardware Ingest” с примером payload на основе bible/docs/import-example-full.json

Идемпотентность

  1. Хеш считается от канонически marshaled hardware request.
  2. Если hash уже есть:
    • без side effects
    • 200 duplicate=true
  3. Если hash новый:
    • полный pipeline
    • 201

Тесты и acceptance

  1. TestIngestHardwareIdempotent: 201 -> 200 duplicate, без дублей в log_bundles/observations/installations.
  2. Тест авто-создания служебного customer/project и auto-create asset.
  3. Тест замены компонента: REMOVED + INSTALLED.
  4. Тест firmware change: FIRMWARE_CHANGED.
  5. Тест статусов:
    • Warning -> COMPONENT_WARNING
    • Critical -> COMPONENT_FAILED + failure_events
  6. Validation tests:
    • missing required fields
    • invalid RFC3339
    • unknown field -> 400
  7. UI smoke: /ui/ingest содержит форму hardware ingest.

Assumptions and defaults

  1. Служебные записи:
    • customer.name = Без заказчика
    • project.name = Без проекта
  2. При дублях по имени используется запись с минимальным id.
  3. manufacturer/product_name == "NULL" -> NULL в БД.
  4. Новые event_type (COMPONENT_WARNING, COMPONENT_FAILED) хранятся как строки без enum-миграции.
  5. /ingest/logbundle остается полностью совместимым.