import { L2_TEMPLATE_SCHEMA_VERSION, PROVIDER_PACKAGE_SCHEMA_VERSION, SEMANTIC_MAPPING_SCHEMA_VERSION, } from "../../../src/provider-package.mjs"; export const GELIOS_PROVIDER_PACKAGE_ID = "gelios.provider.v1"; export const GELIOS_PROVIDER_PACKAGE_VERSION = "1.0.0"; export const GELIOS_POSITIONS_DATA_PRODUCT_ID = "fleet.positions.current.v1"; export const GELIOS_POSITIONS_DATA_PRODUCT_VERSION = "1.0.0"; export const GELIOS_POSITIONS_ONTOLOGY_REVISION = "ontology.map.moving_object.v1"; export const GELIOS_UNIT_SOURCE_ID_PREFIX = "gelios-unit-"; const targetFields = Object.freeze([ "course_degrees", "display_name", "elevation_meters", "geometry", "hdop", "horizontal_accuracy_meters", "object_kind", "operational_status", "position_source", "position_valid", "quality_flags", "satellite_count", "speed_kph", ]); export const geliosProviderPackageV1 = deepFreeze({ schemaVersion: PROVIDER_PACKAGE_SCHEMA_VERSION, id: GELIOS_PROVIDER_PACKAGE_ID, providerId: "gelios", version: GELIOS_PROVIDER_PACKAGE_VERSION, manifest: { id: "gelios.provider.manifest.v1", providerId: "gelios", version: GELIOS_PROVIDER_PACKAGE_VERSION, ontology: { packageId: "gelios", revision: "ontology.gelios.v1", }, authModeIds: ["gelios.rest-bearer.v1"], capabilityIds: ["gelios.units.current.read"], fieldPolicyIds: ["gelios.positions.current.fields.v1"], collectionProfileIds: [ "gelios.positions.current.realtime.v1", "gelios.positions.current.manual.v1", ], dataProductIds: [GELIOS_POSITIONS_DATA_PRODUCT_ID], mappingContractIds: ["gelios.units.to.fleet.positions.current.v1"], l2TemplateIds: ["gelios.positions.current.l2.v1"], }, authModes: [{ id: "gelios.rest-bearer.v1", kind: "api_token", credentialOwner: "ndc_l2_credentials", bindingCardinality: "one_per_connection", transport: { placement: "header", name: "Authorization", }, tokenLifecycle: { artifacts: ["access", "refresh"], requestArtifact: "access", refreshMode: "operator_managed", }, secretHandling: { store: "ndc_l2_credentials", exposeToGraph: false, persistInPackage: false, }, }], capabilities: [{ id: "gelios.units.current.read", classification: "read", status: "implemented", authModeId: "gelios.rest-bearer.v1", request: { method: "GET", baseUrl: "https://api.geliospro.com", path: "/api/v1/units", query: {}, response: { collectionPaths: ["units", "data", "data.units", "result", "$"], pagination: "single_bounded_response", }, }, entityScope: { mode: "all_visible_to_credential", refresh: "each_collection_run", businessEntityFilter: "forbidden", }, }], fieldPolicies: [{ id: "gelios.positions.current.fields.v1", version: "1.0.0", dataProductId: GELIOS_POSITIONS_DATA_PRODUCT_ID, targetFields: [...targetFields], unknownSourceFields: "drop", dynamicSourceFields: "drop_until_classified", restrictedSourcePaths: [ "decrypt_key", "hw_id", "imei", "info", "lmsg.address", "lmsg.params", "lmsg.sensors", "lastMsg.address", "lastMsg.params", "lastMsg.sensors", "lastMessage.address", "lastMessage.params", "lastMessage.sensors", "phone", "phone2", "sensors", ], }], collectionProfiles: [{ id: "gelios.positions.current.realtime.v1", version: "1.0.0", mode: "realtime", schedule: { intervalMs: 10000 }, capabilityIds: ["gelios.units.current.read"], dataProductId: GELIOS_POSITIONS_DATA_PRODUCT_ID, mappingContractId: "gelios.units.to.fleet.positions.current.v1", fieldPolicyId: "gelios.positions.current.fields.v1", l2TemplateId: "gelios.positions.current.l2.v1", entityScope: { mode: "all_visible_to_credential", refresh: "each_collection_run", businessEntityFilter: "forbidden", }, batching: { maxFacts: 5000 }, cardinality: { maxCurrentEntities: 5000, onExceed: "require_partitioned_data_product", }, retry: { maxAttempts: 4, backoff: "exponential_with_jitter", }, }, { id: "gelios.positions.current.manual.v1", version: "1.0.0", mode: "manual", capabilityIds: ["gelios.units.current.read"], dataProductId: GELIOS_POSITIONS_DATA_PRODUCT_ID, mappingContractId: "gelios.units.to.fleet.positions.current.v1", fieldPolicyId: "gelios.positions.current.fields.v1", l2TemplateId: "gelios.positions.current.l2.v1", entityScope: { mode: "all_visible_to_credential", refresh: "each_collection_run", businessEntityFilter: "forbidden", }, batching: { maxFacts: 5000 }, cardinality: { maxCurrentEntities: 5000, onExceed: "require_partitioned_data_product", }, retry: { maxAttempts: 4, backoff: "exponential_with_jitter", }, }], dataProducts: [{ id: GELIOS_POSITIONS_DATA_PRODUCT_ID, version: GELIOS_POSITIONS_DATA_PRODUCT_VERSION, ontologyRevision: GELIOS_POSITIONS_ONTOLOGY_REVISION, deliveryMode: "snapshot+patch", semanticTypes: ["map.moving_object"], fields: [...targetFields], history: { mode: "sampled", intervalMs: 60000, strategy: "latest-per-entity-per-bucket", retentionDays: 90, }, }], mappingContracts: [{ schemaVersion: SEMANTIC_MAPPING_SCHEMA_VERSION, id: "gelios.units.to.fleet.positions.current.v1", version: "1.0.0", sourceCapabilityId: "gelios.units.current.read", fieldPolicyId: "gelios.positions.current.fields.v1", target: { dataProductId: GELIOS_POSITIONS_DATA_PRODUCT_ID, version: GELIOS_POSITIONS_DATA_PRODUCT_VERSION, ontologyRevision: GELIOS_POSITIONS_ONTOLOGY_REVISION, semanticType: "map.moving_object", }, derivations: { position_valid: { kind: "boolean_rule", rules: [ "geometry.coordinates_finite_wgs84", "provider.gps_valid_not_false", ], default: false, }, operational_status: { kind: "ordered_rules", rules: [ "position_invalid.no_position", "observed_age_gt_limit.stale", "otherwise.active", ], default: "active", parameters: { staleAfterMs: 60000 }, }, quality_flags: { kind: "flag_set", rules: [ "geometry_missing.missing_geometry", "provider_gps_false.gps_invalid", "satellite_count_zero.no_satellites", "observed_age_gt_limit.stale", ], default: [], parameters: { staleAfterMs: 60000 }, }, }, fact: { sourceId: { strategy: "first_non_empty", paths: ["id", "unit_id", "unitId"], coerce: "string", prefix: GELIOS_UNIT_SOURCE_ID_PREFIX, }, semanticType: { constant: "map.moving_object" }, observedAt: { strategy: "first_non_empty", paths: [ "lmsg.time", "lmsg.ts", "lmsg.timestamp", "last_msg.time", "last_msg.timestamp", "lastMsg.time", "lastMessage.time", "last_msg_time", "lmsg_time", ], coerce: "unix_or_iso_timestamp", fallback: "collection_received_at", }, geometry: { type: "Point", longitude: { strategy: "first_non_empty", paths: ["lmsg.lon", "lmsg.lng", "lmsg.longitude", "last_msg.lon", "lastMsg.lon", "lastMsg.lng", "lastMsg.longitude", "lastMessage.lon", "lastMessage.lng", "lastMessage.longitude", "lon", "lng", "longitude"], coerce: "number", }, latitude: { strategy: "first_non_empty", paths: ["lmsg.lat", "lmsg.latitude", "last_msg.lat", "lastMsg.lat", "lastMsg.latitude", "lastMessage.lat", "lastMessage.latitude", "lat", "latitude"], coerce: "number", }, omitIfInvalid: true, }, attributes: { course_degrees: { strategy: "first_non_empty", paths: ["lmsg.course", "lmsg.angle", "last_msg.course", "lastMsg.course", "lastMsg.angle", "lastMessage.course", "lastMessage.angle", "course"], coerce: "number", omitIfMissing: true, }, display_name: { strategy: "first_non_empty", paths: ["name", "unit_name", "title", "label"], coerce: "string", }, elevation_meters: { strategy: "first_non_empty", paths: ["lmsg.height", "lmsg.altitude", "last_msg.height", "lastMsg.height", "lastMsg.altitude", "lastMessage.height", "lastMessage.altitude", "height", "altitude"], coerce: "number", omitIfMissing: true, }, hdop: { strategy: "first_non_empty", paths: ["lmsg.hdop", "last_msg.hdop", "lastMsg.hdop", "lastMessage.hdop", "gps_hdop", "hdop"], coerce: "number", omitIfMissing: true, }, horizontal_accuracy_meters: { strategy: "first_non_empty", paths: ["lmsg.accuracy", "last_msg.accuracy", "lastMsg.accuracy", "lastMessage.accuracy", "gps_accuracy_m", "accuracy_m", "accuracy"], coerce: "number", omitIfMissing: true, }, object_kind: { constant: "tracked_unit" }, operational_status: { derive: "operational_status" }, position_source: { constant: "gelios" }, position_valid: { derive: "position_valid" }, quality_flags: { derive: "quality_flags" }, satellite_count: { strategy: "first_non_empty", paths: ["lmsg.sats", "lmsg.satellites", "last_msg.sats", "lastMsg.sats", "lastMsg.satellites", "lastMessage.sats", "lastMessage.satellites", "gps_sats", "sats", "satellites"], coerce: "number", omitIfMissing: true, }, speed_kph: { strategy: "first_non_empty", paths: ["lmsg.speed", "last_msg.speed", "lastMsg.speed", "lastMessage.speed", "speed"], coerce: "number", omitIfMissing: true, }, }, }, }], l2Templates: [{ schemaVersion: L2_TEMPLATE_SCHEMA_VERSION, id: "gelios.positions.current.l2.v1", version: "1.0.0", runtime: "ndc_l2", instanceMode: "one_connection_per_workflow", connectionParameters: [ "tenant_id", "connection_id", "collection_profile_id", "provider_credential_ref", ], credentialBindings: [{ role: "provider", owner: "ndc_l2_credentials", management: "connection_input", authModeId: "gelios.rest-bearer.v1", }, { role: "publisher", owner: "ndc_l2_credentials", management: "control_plane_managed", nodeType: "n8n-nodes-ndc.ndcDataProductPublish", }], steps: [{ id: "collection.trigger", kind: "collection_trigger", collectionProfileDriven: true, }, { id: "provider.fetch", kind: "provider_request", capabilityId: "gelios.units.current.read", }, { id: "provider.extract-items", kind: "extract_items", capabilityId: "gelios.units.current.read", }, { id: "ontology.map", kind: "semantic_mapping", mappingContractId: "gelios.units.to.fleet.positions.current.v1", }, { id: "data-product.publish", kind: "data_product_publish", dataProductId: GELIOS_POSITIONS_DATA_PRODUCT_ID, nodeType: "n8n-nodes-ndc.ndcDataProductPublish", }], invariants: { oneConnectionPerInstance: true, providerSecretByReferenceOnly: true, publisherBindingControlPlaneManaged: true, callerScopeForbidden: true, providerSpecificServiceForbidden: true, }, }], }); function deepFreeze(value) { if (!value || typeof value !== "object" || Object.isFrozen(value)) return value; Object.freeze(value); for (const child of Object.values(value)) deepFreeze(child); return value; }