- 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>
4.6 KiB
4.6 KiB
Data Model And Migration Boundaries
Naming Model
- Internal canonical naming uses
MachineandPart. - API/UI compatibility keeps
assetandcomponentterminology where already exposed. - In domain aliases:
type Asset = Machinetype Component = Part
Core Persistence Areas
- Asset registry:
machines - Component registry:
parts - Installations:
installations - Observations:
observations - Timeline:
timeline_events - Failures:
failure_events - Asset firmware state:
machine_firmware_states - Asset sensor readings:
machine_sensor_readings - Component history (canonical):
component_change_events,component_state_snapshots - Asset history (canonical):
asset_change_events,asset_state_snapshots - History jobs/audit:
history_recompute_jobs,history_admin_audit
Sensor Readings
machine_sensor_readings is a last-known-value projection for hardware sensors per asset.
- Primary key:
(machine_id, sensor_type, sensor_name). sensor_typeis one of:fan,power,temperature,other.value_jsonstores type-specific numeric readings (see JSON import contract).- Updated on every ingest — not history-backed (no events, no snapshots).
collected_atreflects the source observation time, not ingest time.
Out of active model:
projectsis legacy and not used by runtime handlers/contracts.
Migration Policy
- Migrations are stored in
migrations/. - Schema migrations are applied at startup.
- Legacy entities removed in migration
0016_remove_legacy_featuresremain out of active scope. - History architecture was introduced in migration
0017_history_core. - Timeline UI/filter denormalized facets were added in migration
0018_timeline_ui_facets. - Installation slot/location (
installations.slot_name) was added in migration0019_installation_slot_name. - History-first
component_typeprojection/storage backfill was introduced in migration0020_component_type_history_first.
Canonical State Model (History-First)
partsandmachinesare current-state projections optimized for reads.component_change_events/asset_change_eventsare canonical state-change logs.component_state_snapshots/asset_state_snapshotsstore full after-state snapshots for each state-changing event.timeline_events,installations,failure_events, andmachine_firmware_statesare projections and may be rebuilt from history.observationsis a raw ingest trace/audit store and must not be used as source-of-truth for current component/asset state in runtime UI/API flows.parts.component_typeandinstallations.slot_nameare the runtime-readable projections for component type and current slot/location (notobservations.details).
History Event Storage Rules
- History events are versioned per entity (
versionis monotonic per component/asset). - State-changing writes persist:
- change event
- after-state snapshot
- projection updates (
parts/machinesand related projections) - timeline projection rows
- History event deletion is soft-delete (
is_deleted) for normal user/admin flow. - Hard restore is destructive for future history rows and is audited in
history_admin_audit.
Timeline Projection Linkage
timeline_events includes logical linkage back to history:
logical_entity_typelogical_event_idcorrelation_idis_deleted
This linkage is required for recompute, rollback/delete propagation, and paired asset/component timeline rendering.
timeline_events also stores denormalized UI/filter facets (projection-only, rebuildable from history + registry state), including:
source_typevisual_actioncomponent_serialcomponent_model(used as v1part_number)asset_serialasset_name_cachedslot_namedevice_namechanged_fields_json
These fields are not canonical state and must be treated as timeline projection helpers only.
Installation Slot (Current Components UI)
installations.slot_nameis the canonical editable slot/location for a component attached to a server.- Asset page
Current Componentsbulk actions (Add / Edit / Remove) read/write slot through history-driven component installation state (installation.slot_namein component snapshots) and synchronize projectioninstallations.slot_name. - Runtime invariant (app-level validation):
- for the same
machine_id, open installations (removed_at IS NULL) must not share the same non-emptyslot_name.
- for the same
- Projection-update nuance:
- slot uniqueness validation must only block writes when
slot_nameis actually changing for the installation row (status-only edits must not fail because of pre-existing duplicate slot data).
- slot uniqueness validation must only block writes when