Auditors can now send BIOS/Redfish platform settings via
POST /ingest/hardware as hardware.platform_config (map[string]any).
Stored as latest-snapshot per machine with per-key change history.
Exposed via GET /api/assets/{id}/platform-config and .../history.
Asset page gets a third tab "Platform Config" with inline history expand.
Contract bumped to v2.9, migration 0024 adds two new tables.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allow COMPONENT_REMOVED patches to bypass server-only restriction on
/installation/* paths so manual de-assert works for user source type.
Group vendors with <1% share into "Others" in the Vendor Distribution
chart; cap total slices at 15.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add HardwareSensors to JSON contract: fans, power, temperatures, other
- Add machine_sensor_readings table (migration 0022) with upsert in ingest service
- Add mac_addresses []string to HardwarePCIeDevice
- Expand device_class examples: VideoController, ProcessingAccelerator,
EthernetController, FibreChannelController, StorageController
- Add distributable hardware-ingest-contract.md v2.1 with versioning,
changelog, field tables, and canonical URL
- Add governance rule: contract doc must be updated with every parser change
- Update data-model.md to document machine_sensor_readings projection
- Update both import-example-full.json files with sensors and new PCIe entries
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Migrate all log.Printf/log.Fatalf to log/slog with structured key-value
attributes per bible go-logging contract.
- Add withRequestID middleware: generates crypto/rand 8-byte hex ID per
request, sets X-Request-ID response header, injects into context
- withErrorLogging uses slog with request_id from context
- writeError internal log calls migrated to slog.Error/slog.Warn
- All handler log calls in api, ingest, history packages use slog
- cmd/reanimator-api configures slog.NewTextHandler(os.Stdout) at startup
- cmd/reanimator-migrate, cmd/reanimator-reset migrated to slog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implement release note discipline per bible module-versioning contract:
- Add version.go with Version = "1.0" to ingest, history, api packages
- Drop CI task (no CI infrastructure planned)
- Drop Release note discipline task (now implemented)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove OpenAPI spec from Cross-Cutting Tasks: no external consumers,
API surface already documented in api-surface.md
- Remove Phase 3 (entity renaming assets->machines/components->parts):
API surface keeps asset/component naming per architecture decision,
DB rename has no user-visible value and high migration risk
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- history/worker: fix deadlock by moving stale job requeue out of claimNextJob
into dedicated staleJobRequeuer goroutine (runs every 2 min)
- history/service,tx_apply,cross_entity: add deferred=true mode — write events+
snapshots but skip projection updates; queue recompute after commit
- ingest/service: IngestHardwareDeferred uses deferred mode; CSV workers up to 8
(INGEST_CSV_WORKERS env); serial/prefetch lookups use normalize.SerialKey
- api/ingest: JSON /ingest/hardware now async (202 + job_id); new GET
/ingest/hardware/jobs/{id} endpoint; CSV already async
- history/admin_cancel: replace per-event softDelete loop with batchSoftDeleteEvents
using IN-clause chunks of 500 to prevent request timeout on large deletes
- normalize: new internal/normalize package with VendorKey, VendorDisplay,
VendorDisplayPtr, SerialKey, FirmwareKey
- ingest/parser_hardware: vendor fields use normalize.VendorDisplayPtr
- migrations/0021_ci_identifiers: change identifier columns to utf8mb4_unicode_ci
(case-insensitive) in parts, machines, observations, machine_firmware_states
- bible submodule: update to add identifier-normalization contract
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Dashboard: line charts (assets over time, components total + uninstalled)
with filled areas, shared x-axis (Mon YYYY), auto-formatted y-labels (1k/1M)
and global start date derived from earliest FirstSeenAt across components
- /ui/ingest/history: source type chips (Ingest / CSV Import / Manual / System)
- /ui/component/models: firmware version count column, column filters,
sortable headers, vendor distribution pie chart
- /ui/component/{vendor}/{model}: firmware version summary table with
per-version healthy/unknown/failed counts, failed rows highlighted
- /ui/component/uninstalled: new page + nav item; components not installed
on any server, two-level grouping by vendor then model (collapsed by default)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- Add new section "Post-MVP UI Enhancements" with all completed tasks
- Update progress snapshot with current date and status
- Document date formatting, breadcrumbs, menu restructuring, and clickable rows
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Format dates as YYYY-MM-DD with full timestamp on hover
- Add breadcrumb navigation with hospital icon (🏥) across all pages
- Restructure main menu with grouped dropdowns:
* Hardware (Assets, Components)
* Health (Tickets, Failures, Analytics)
* Settings (Ingest)
- Make table rows clickable on Dashboard, Assets, and Components pages
- Add new Customers page with list view
- Improve dropdown menu stability with JS hover delay
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixes 400 Bad Request error when ingesting hardware snapshots that include
PCIe link speed information (link_width, link_speed, max_link_width, max_link_speed).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>