feat(provider): catalogue complete Gelios data surface
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
# Gelios capability catalog
|
||||
|
||||
`capability-catalog-v1.mjs` is the complete classified inventory for the
|
||||
current `UnitModelOutput` surface and the adjacent object APIs that NODE.DC may
|
||||
consume. Its authority is the official Gelios OpenAPI, checked on 2026-07-22.
|
||||
|
||||
The catalog is deliberately separate from an active L2 package. `implemented`
|
||||
means a capability already has a governed collection and Data Product path;
|
||||
`catalogued` means NODE.DC understands the surface but has not activated it;
|
||||
`disabled` is mandatory for control and destructive operations.
|
||||
|
||||
The catalog accounts for every top-level Unit field and all twelve official
|
||||
`/api/v1/units` include flags. It also records the separate read surfaces for
|
||||
sensor metadata, latest sensor values, maintenance, filling, schedules and
|
||||
command audit. Raw messages, decrypt material and command execution never
|
||||
enter an operational UI projection.
|
||||
|
||||
Cadence is a product boundary:
|
||||
|
||||
- `hot`: current position, state, counters and classified latest readings;
|
||||
- `warm`: slowly changing operational records such as maintenance plans;
|
||||
- `cold`: unit, equipment and calculation profiles;
|
||||
- `on_demand`: restricted or historical details that need explicit policy;
|
||||
- `never`: secret, raw or command material outside the telemetry plane.
|
||||
|
||||
Provider packages may implement catalogued families incrementally, but they
|
||||
must not move fields between classifications or cadences implicitly. A new
|
||||
Data Product and its Foundry subject aspect must be explicit and versioned.
|
||||
@@ -0,0 +1,332 @@
|
||||
import { PROVIDER_CAPABILITY_CATALOG_SCHEMA_VERSION } from "../../src/provider-capability-catalog.mjs";
|
||||
|
||||
const unitCapabilityId = "gelios.units.current.read";
|
||||
|
||||
export const geliosCapabilityCatalogV1 = deepFreeze({
|
||||
schemaVersion: PROVIDER_CAPABILITY_CATALOG_SCHEMA_VERSION,
|
||||
providerId: "gelios",
|
||||
version: "1.0.0",
|
||||
authority: {
|
||||
kind: "official-openapi",
|
||||
url: "https://api.geliospro.com/openapi.json",
|
||||
checkedAt: "2026-07-22T15:30:00Z",
|
||||
},
|
||||
coverage: {
|
||||
schemaId: "UnitModelOutput",
|
||||
sourceRoots: [
|
||||
"activatedAt", "availableToUsers", "blockTime", "commands", "counters", "createdAt",
|
||||
"creator", "currentUserAccess", "customFields", "driver", "extraInfo", "fuelParams",
|
||||
"hwDecryptKey", "hwManufacturer", "hwType", "id", "imei", "imeiIsVisible", "isBlock",
|
||||
"isFree", "lastMsg", "lastSensorsVal", "maintenancePlan", "name", "phone", "phone2",
|
||||
"phone2IsVisible", "phoneIsVisible", "preSetCommandGroup", "removed", "removedAt", "sensors",
|
||||
"stationaryLat", "stationaryLon", "storageInfo", "tripParams", "unblockTime", "unitType",
|
||||
],
|
||||
},
|
||||
queryFlags: [
|
||||
flag("inclextra", ["gelios.unit.asset_profile", "gelios.unit.asset_identifiers", "gelios.unit.extra_internal"]),
|
||||
flag("incltrip", ["gelios.unit.trip_settings"]),
|
||||
flag("inclfuel", ["gelios.unit.fuel_settings"]),
|
||||
flag("inclcntrs", ["gelios.unit.counters"]),
|
||||
flag("inclcstmflds", ["gelios.unit.custom_fields"]),
|
||||
flag("inclsnsrs", ["gelios.unit.sensor_definitions", "gelios.unit.sensor_conversion"]),
|
||||
flag("inclcmmnds", ["gelios.unit.command_catalog"]),
|
||||
flag("incldrvrs", ["gelios.unit.driver"]),
|
||||
flag("inclstinf", ["gelios.unit.storage"]),
|
||||
flag("inclusersav", ["gelios.unit.access_metadata"]),
|
||||
flag("incllsv", ["gelios.unit.latest_sensor_values"]),
|
||||
flag("inclplan", ["gelios.unit.maintenance_plan"]),
|
||||
],
|
||||
dataFamilies: [
|
||||
family({
|
||||
id: "gelios.unit.identity",
|
||||
title: "Stable unit identity and type",
|
||||
sourcePaths: ["id", "name", "unitType.id", "unitType.name", "unitType.type"],
|
||||
cadence: "cold", classification: "operational", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.unit"], uiTab: "overview",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.lifecycle",
|
||||
title: "Activation, blocking and removal lifecycle",
|
||||
sourcePaths: ["activatedAt", "blockTime", "createdAt", "isBlock", "isFree", "removed", "removedAt", "unblockTime"],
|
||||
cadence: "cold", classification: "operational", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.unit"], uiTab: "overview",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.access_metadata",
|
||||
title: "Provider ownership and access metadata",
|
||||
sourcePaths: ["availableToUsers[]", "creator.id", "creator.login", "currentUserAccess"],
|
||||
cadence: "cold", classification: "internal", disposition: "catalogue", status: "catalogued",
|
||||
ontologyEntities: ["gelios.unit"],
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.equipment",
|
||||
title: "Tracker hardware classification",
|
||||
sourcePaths: ["hwManufacturer.id", "hwManufacturer.name", "hwType.id", "hwType.name"],
|
||||
cadence: "cold", classification: "operational", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.tracker_device"], uiTab: "equipment",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.device_identifiers",
|
||||
title: "Restricted device and phone identifiers",
|
||||
sourcePaths: ["imei", "imeiIsVisible", "phone", "phone2", "phone2IsVisible", "phoneIsVisible"],
|
||||
cadence: "on_demand", classification: "restricted", disposition: "profile", status: "catalogued",
|
||||
ontologyEntities: ["gelios.tracker_device"], uiTab: "equipment",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.cryptographic_material",
|
||||
title: "Provider cryptographic material",
|
||||
sourcePaths: ["hwDecryptKey"],
|
||||
cadence: "never", classification: "secret", disposition: "forbid", status: "forbidden",
|
||||
ontologyEntities: ["gelios.tracker_device"],
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.stationary_location",
|
||||
title: "Restricted configured stationary location",
|
||||
sourcePaths: ["stationaryLat", "stationaryLon"],
|
||||
cadence: "on_demand", classification: "restricted", disposition: "profile", status: "catalogued",
|
||||
ontologyEntities: ["gelios.unit"], uiTab: "position",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.position_current",
|
||||
title: "Current normalized position and movement sample",
|
||||
sourcePaths: [
|
||||
"lastMsg.course", "lastMsg.height", "lastMsg.lat", "lastMsg.lon", "lastMsg.receiveTime",
|
||||
"lastMsg.sats", "lastMsg.speed", "lastMsg.time",
|
||||
],
|
||||
cadence: "hot", classification: "operational", disposition: "publish", status: "implemented",
|
||||
ontologyEntities: ["gelios.telemetry_snapshot", "map.moving_object"], uiTab: "position",
|
||||
dataProductIds: ["fleet.positions.current.v5"],
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.raw_message_parameters",
|
||||
title: "Unclassified raw tracker message parameters",
|
||||
sourcePaths: ["lastMsg.params"],
|
||||
cadence: "never", classification: "unclassified", disposition: "forbid", status: "forbidden",
|
||||
ontologyEntities: ["gelios.telemetry_snapshot"],
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.counters",
|
||||
title: "Operational mileage and engine-hour counters",
|
||||
sourcePaths: ["counters.engineHours.value", "counters.mileage.value"],
|
||||
cadence: "hot", classification: "operational", disposition: "publish", status: "implemented",
|
||||
ontologyEntities: ["gelios.telemetry_snapshot"], uiTab: "counters",
|
||||
dataProductIds: ["fleet.positions.current.v5"],
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.latest_sensor_values",
|
||||
title: "Latest values for explicitly classified sensors",
|
||||
sourcePaths: ["lastSensorsVal[].tm", "lastSensorsVal[].val"],
|
||||
cadence: "hot", classification: "unclassified", disposition: "profile", status: "implemented",
|
||||
ontologyEntities: ["gelios.sensor_reading"], uiTab: "telemetry",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.sensor_definitions",
|
||||
title: "Sensor identity, units, visibility and limits",
|
||||
sourcePaths: [
|
||||
"sensors[].displayFuelTankVolume", "sensors[].fuelConsumptionRate", "sensors[].fuelTankVolume",
|
||||
"sensors[].id", "sensors[].isVisible", "sensors[].maxValidParamValue", "sensors[].measure",
|
||||
"sensors[].minValidParamValue", "sensors[].msgParam", "sensors[].name", "sensors[].type.id", "sensors[].type.name",
|
||||
],
|
||||
cadence: "cold", classification: "unclassified", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.sensor_definition"], uiTab: "equipment",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.sensor_conversion",
|
||||
title: "Raw sensor conversion tables",
|
||||
sourcePaths: ["sensors[].conversionTable"],
|
||||
cadence: "cold", classification: "internal", disposition: "catalogue", status: "catalogued",
|
||||
ontologyEntities: ["gelios.sensor_definition"],
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.asset_profile",
|
||||
title: "Vehicle and asset descriptive profile",
|
||||
sourcePaths: [
|
||||
"extraInfo.brand", "extraInfo.color", "extraInfo.engineCubicCapacity", "extraInfo.enginePower",
|
||||
"extraInfo.fuelType", "extraInfo.iconLink", "extraInfo.model", "extraInfo.year",
|
||||
],
|
||||
cadence: "cold", classification: "operational", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.unit"], uiTab: "equipment",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.asset_identifiers",
|
||||
title: "Restricted VIN and number plate",
|
||||
sourcePaths: ["extraInfo.numberPlate", "extraInfo.vin"],
|
||||
cadence: "on_demand", classification: "restricted", disposition: "profile", status: "catalogued",
|
||||
ontologyEntities: ["gelios.unit"], uiTab: "equipment",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.extra_internal",
|
||||
title: "Provider autocomplete metadata",
|
||||
sourcePaths: ["extraInfo.autocompleteParams"],
|
||||
cadence: "cold", classification: "internal", disposition: "catalogue", status: "catalogued",
|
||||
ontologyEntities: ["gelios.unit"],
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.trip_settings",
|
||||
title: "Trip detection and movement policy",
|
||||
sourcePaths: prefixed("tripParams", [
|
||||
"correctedEngineHoursFactor", "correctedMileageFactor", "filterBySatellitesCountIsOn",
|
||||
"filterBySatellitesCountValue", "filterEmissions", "limitAcceleration", "lostConnectionIsOn",
|
||||
"lostConnectionTimeValue", "maximumPermissibleSpeed", "maximumValidHeight", "maximumValidSpeed",
|
||||
"mileageByIgnition", "minimumMovementSpeed", "minimumMovementTime", "minimumParkingTime",
|
||||
"minimumTimeStop", "minimumTripDistance", "minimumValidHeight", "speedMeasurementItemsId",
|
||||
"speedParam", "tripDetectionType.id", "tripDetectionType.name", "useOdometer",
|
||||
]),
|
||||
cadence: "cold", classification: "operational", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.unit"], uiTab: "settings",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.fuel_settings",
|
||||
title: "Fuel calculation and theft/filling policy",
|
||||
sourcePaths: prefixed("fuelParams", [
|
||||
"cityConsumptionSummer", "cityConsumptionWinter", "fillingByIgnOff", "fillingInterval",
|
||||
"fillingSplitTimeout", "fillingTheftOnParkingOnly", "filterZeroFls", "idleConsumptionSummer",
|
||||
"idleConsumptionWinter", "ignoreMsgsTimeAfterStart", "includeTheftsInConsumption",
|
||||
"maximumConsumptionForPeriod", "minimumFilling", "minimumFuelTheft", "outOfTheCityConsumptionSummer",
|
||||
"outOfTheCityConsumptionWinter", "secondsToIgnoreAfterMovementStart", "theftByIgnOff",
|
||||
"theftSplitTimeout", "useAverageFlsValue", "useFilterIsOn", "useFilterValue",
|
||||
"useNewFuelCalcAlgorithm", "useSeparateFls", "winterEnd", "winterStart",
|
||||
]),
|
||||
cadence: "cold", classification: "operational", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.fuel_profile"], uiTab: "settings",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.maintenance_plan",
|
||||
title: "Maintenance thresholds and progress",
|
||||
sourcePaths: prefixed("maintenancePlan[]", [
|
||||
"created_at", "description", "id", "interval_day", "interval_mileage", "interval_motohour",
|
||||
"is_day", "is_mileage", "is_motohour", "last_day", "last_mileage", "last_motohour",
|
||||
"name", "repeat_count", "total_count", "unit_id", "updated_at",
|
||||
]),
|
||||
cadence: "warm", classification: "operational", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.maintenance_plan"], uiTab: "maintenance",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.custom_fields",
|
||||
title: "Tenant-defined fields requiring explicit classification",
|
||||
sourcePaths: ["customFields[].id", "customFields[].isVisible", "customFields[].name", "customFields[].value"],
|
||||
cadence: "cold", classification: "unclassified", disposition: "profile", status: "catalogued",
|
||||
ontologyEntities: ["gelios.custom_field"], uiTab: "diagnostics",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.driver",
|
||||
title: "Driver personal data",
|
||||
sourcePaths: ["driver.name", "driver.phone"],
|
||||
cadence: "on_demand", classification: "restricted", disposition: "profile", status: "catalogued",
|
||||
ontologyEntities: ["gelios.unit"],
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.storage",
|
||||
title: "Provider storage policy",
|
||||
sourcePaths: [
|
||||
"storageInfo.storagePeriod.description", "storageInfo.storagePeriod.id", "storageInfo.storagePeriod.name",
|
||||
"storageInfo.storagePeriodLastUpdUtc",
|
||||
],
|
||||
cadence: "cold", classification: "operational", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.unit"], uiTab: "equipment",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.command_catalog",
|
||||
title: "Command templates and preset groups",
|
||||
sourcePaths: [
|
||||
"commands[].id", "commands[].name", "commands[].text", "commands[].type",
|
||||
"preSetCommandGroup.id", "preSetCommandGroup.name",
|
||||
],
|
||||
cadence: "never", classification: "control", disposition: "catalogue", status: "catalogued",
|
||||
ontologyEntities: ["integration.command_capability"],
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.maintenance_events",
|
||||
title: "Maintenance event history",
|
||||
sourcePaths: ["maintenanceEvents[].id", "maintenanceEvents[].date", "maintenanceEvents[].description"],
|
||||
cadence: "on_demand", classification: "operational", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.maintenance_plan"], uiTab: "maintenance",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.filling_events",
|
||||
title: "Fuel filling event history",
|
||||
sourcePaths: ["fillingEvents[].id", "fillingEvents[].date", "fillingEvents[].volume", "fillingEvents[].price"],
|
||||
cadence: "on_demand", classification: "operational", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.fuel_profile"], uiTab: "maintenance",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.work_schedule",
|
||||
title: "Shifts and work-time rules",
|
||||
sourcePaths: ["shifts[].id", "shifts[].name", "workTime[].id", "workTime[].startDay", "workTime[].endDay"],
|
||||
cadence: "cold", classification: "operational", disposition: "profile", status: "planned",
|
||||
ontologyEntities: ["gelios.unit"], uiTab: "settings",
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.command_history",
|
||||
title: "Command execution audit history",
|
||||
sourcePaths: ["commandHistory[].id", "commandHistory[].status", "commandHistory[].timeCmd", "commandHistory[].timeSend"],
|
||||
cadence: "on_demand", classification: "control", disposition: "catalogue", status: "catalogued",
|
||||
ontologyEntities: ["integration.command_capability"],
|
||||
}),
|
||||
family({
|
||||
id: "gelios.unit.raw_messages",
|
||||
title: "Pure and raw tracker messages",
|
||||
sourcePaths: ["rawMessages[].payload"],
|
||||
cadence: "never", classification: "restricted", disposition: "forbid", status: "forbidden",
|
||||
ontologyEntities: ["gelios.telemetry_snapshot"],
|
||||
}),
|
||||
family({
|
||||
id: "gelios.geozones.current",
|
||||
title: "Provider geozone catalogue",
|
||||
sourcePaths: ["geozones[].geometry", "geozones[].id", "geozones[].name"],
|
||||
cadence: "cold", classification: "operational", disposition: "publish", status: "implemented",
|
||||
ontologyEntities: ["map.zone"], dataProductIds: ["map.gelios-geofences.current.v1"],
|
||||
}),
|
||||
],
|
||||
capabilities: [
|
||||
capability("gelios.units.current.read", "GET", "/api/v1/units", "read", "implemented", [
|
||||
"gelios.unit.identity", "gelios.unit.lifecycle", "gelios.unit.access_metadata", "gelios.unit.equipment",
|
||||
"gelios.unit.device_identifiers", "gelios.unit.cryptographic_material", "gelios.unit.stationary_location",
|
||||
"gelios.unit.position_current", "gelios.unit.raw_message_parameters", "gelios.unit.counters",
|
||||
"gelios.unit.latest_sensor_values", "gelios.unit.sensor_definitions", "gelios.unit.sensor_conversion",
|
||||
"gelios.unit.asset_profile", "gelios.unit.asset_identifiers", "gelios.unit.extra_internal",
|
||||
"gelios.unit.trip_settings", "gelios.unit.fuel_settings", "gelios.unit.maintenance_plan",
|
||||
"gelios.unit.custom_fields", "gelios.unit.driver", "gelios.unit.storage", "gelios.unit.command_catalog",
|
||||
]),
|
||||
capability("gelios.unit.current.read", "GET", "/api/v1/units/{unit_id}", "read", "catalogued", ["gelios.unit.identity"]),
|
||||
capability("gelios.units.last_messages.read", "POST", "/api/v1/units/last-msgs/full", "read", "catalogued", ["gelios.unit.position_current"]),
|
||||
capability("gelios.unit.sensors.read", "GET", "/api/v1/units/{unit_id}/sensors", "metadata", "catalogued", ["gelios.unit.sensor_definitions", "gelios.unit.sensor_conversion"]),
|
||||
capability("gelios.unit.sensor_values.read", "GET", "/api/v1/units/{unit_id}/sensors/values/last", "read", "catalogued", ["gelios.unit.latest_sensor_values"]),
|
||||
capability("gelios.unit.maintenance_plan.read", "GET", "/api/v1/units/{unit_id}/maintenance/plan", "read", "catalogued", ["gelios.unit.maintenance_plan"]),
|
||||
capability("gelios.unit.maintenance_events.read", "GET", "/api/v1/units/{unit_id}/maintenance/event", "read", "catalogued", ["gelios.unit.maintenance_events"]),
|
||||
capability("gelios.unit.filling_events.read", "GET", "/api/v1/units/{unit_id}/filling/event", "read", "catalogued", ["gelios.unit.filling_events"]),
|
||||
capability("gelios.unit.shifts.read", "GET", "/api/v1/units/{unit_id}/shifts", "read", "catalogued", ["gelios.unit.work_schedule"]),
|
||||
capability("gelios.unit.work_time.read", "GET", "/api/v1/units/{unit_id}/work-time", "read", "catalogued", ["gelios.unit.work_schedule"]),
|
||||
capability("gelios.unit.command_history.read", "GET", "/api/v1/units/{unit_id}/commands/history", "metadata", "catalogued", ["gelios.unit.command_history"]),
|
||||
capability("gelios.unit.commands.read", "GET", "/api/v1/units/{unit_id}/commands", "metadata", "catalogued", ["gelios.unit.command_catalog"]),
|
||||
capability("gelios.unit.last_message_params.read", "GET", "/api/v1/units/{unit_id}/last-msg-params", "metadata", "catalogued", ["gelios.unit.raw_message_parameters"]),
|
||||
capability("gelios.unit.raw_message.read", "GET", "/api/v1/units/{unit_id}/last-msg/raw", "read", "disabled", ["gelios.unit.raw_messages"]),
|
||||
capability("gelios.geozones.current.read", "GET", "/api/v1/geozones", "read", "implemented", ["gelios.geozones.current"]),
|
||||
capability("gelios.unit.command.send", "POST", "/api/v1/units/{unit_id}/commands/send", "control", "disabled", ["gelios.unit.command_catalog"]),
|
||||
capability("gelios.unit.update", "PATCH", "/api/v1/units/{unit_id}", "write", "disabled", ["gelios.unit.identity"]),
|
||||
capability("gelios.unit.delete", "DELETE", "/api/v1/units/{unit_id}", "destructive", "disabled", ["gelios.unit.lifecycle"]),
|
||||
],
|
||||
});
|
||||
|
||||
function flag(id, familyIds) {
|
||||
return { id, capabilityId: unitCapabilityId, familyIds };
|
||||
}
|
||||
|
||||
function family({ dataProductIds = [], ...value }) {
|
||||
return { ...value, dataProductIds };
|
||||
}
|
||||
|
||||
function capability(id, method, path, classification, status, familyIds) {
|
||||
return { id, method, path, classification, status, familyIds };
|
||||
}
|
||||
|
||||
function prefixed(prefix, fields) {
|
||||
return fields.map((field) => `${prefix}.${field}`);
|
||||
}
|
||||
|
||||
function deepFreeze(input) {
|
||||
if (!input || typeof input !== "object" || Object.isFrozen(input)) return input;
|
||||
Object.freeze(input);
|
||||
for (const child of Object.values(input)) deepFreeze(child);
|
||||
return input;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export { geliosCapabilityCatalogV1 } from "./capability-catalog-v1.mjs";
|
||||
export * from "./v7/index.mjs";
|
||||
Reference in New Issue
Block a user