feat(platform): complete the Gelios external data loop

This commit is contained in:
Codex
2026-07-20 20:45:05 +03:00
parent def9a24e0d
commit 8a7465cf0e
66 changed files with 5730 additions and 123 deletions
@@ -15,6 +15,9 @@ import {
geliosUnitsCurrentFixtureV1,
} from "../providers/gelios/v1/index.mjs";
import { geliosProviderPackageV2 } from "../providers/gelios/v2/index.mjs";
import { geliosProviderPackageV3 } from "../providers/gelios/v3/index.mjs";
import { geliosProviderPackageV4 } from "../providers/gelios/v4/index.mjs";
import { geliosProviderPackageV5 } from "../providers/gelios/v5/index.mjs";
import { normalizeDataProductDefinition } from "../../../services/external-data-plane/src/data-product-policy.mjs";
const expectedFields = [
@@ -35,6 +38,197 @@ const expectedFields = [
assert.deepEqual(validateProviderPackage(geliosProviderPackageV1), { ok: true, errors: [] });
assert.deepEqual(validateProviderPackage(geliosProviderPackageV2), { ok: true, errors: [] });
assert.deepEqual(validateProviderPackage(geliosProviderPackageV3), { ok: true, errors: [] });
assert.deepEqual(validateProviderPackage(geliosProviderPackageV4), { ok: true, errors: [] });
assert.deepEqual(validateProviderPackage(geliosProviderPackageV5), { ok: true, errors: [] });
const strictProduct = geliosProviderPackageV5.dataProducts[0];
const registeredStrictProduct = JSON.parse(await readFile(new URL(
"../../../services/external-data-plane/definitions/fleet.positions.current.v4.json",
import.meta.url,
), "utf8"));
const geliosOntologyEntities = JSON.parse(await readFile(new URL(
"../../../services/ontology-core/catalog/domain-packages/gelios/entities.json",
import.meta.url,
), "utf8"));
assert.equal(geliosProviderPackageV5.id, "gelios.provider.v5");
assert.equal(strictProduct.id, "fleet.positions.current.v4");
assert.deepEqual(strictProduct, registeredStrictProduct);
assert.deepEqual(strictProduct.fieldContracts.signal_state.enum, ["active", "inactive"]);
assert.deepEqual(strictProduct.fieldContracts.movement_state.enum, ["moving", "stopped"]);
for (const ontologyEntityId of ["gelios.signal_state", "gelios.movement_state"]) {
const valueContract = geliosOntologyEntities.entities.find((entity) => entity.id === ontologyEntityId)?.valueContract;
assert.ok(valueContract, `${ontologyEntityId} must expose an Ontology valueContract`);
assert.deepEqual(
strictProduct.fieldContracts[valueContract.field].enum,
valueContract.values.map(({ value: state }) => state),
`${valueContract.field} Data Product enum must equal the Ontology value contract`,
);
}
const withInvalidClosedStateDefault = structuredClone(geliosProviderPackageV5);
withInvalidClosedStateDefault.mappingContracts[0].derivations.signal_state.default = "invented";
assert.equal(
validateProviderPackage(withInvalidClosedStateDefault).errors.includes(
"mappingContract.gelios.units.to.fleet.positions.current.v5.fact.attributes.signal_state.derivation.default_not_in_field_contract_enum",
),
true,
);
const withInvalidClosedStateRule = structuredClone(geliosProviderPackageV5);
withInvalidClosedStateRule.mappingContracts[0].derivations.movement_state.rules[0] = "integer_speed_gt_threshold.teleporting";
assert.equal(
validateProviderPackage(withInvalidClosedStateRule).errors.includes(
"mappingContract.gelios.units.to.fleet.positions.current.v5.fact.attributes.movement_state.derivation.rules[0]_not_in_field_contract_enum",
),
true,
);
const withOptionalRequiredState = structuredClone(geliosProviderPackageV5);
withOptionalRequiredState.mappingContracts[0].fact.attributes.signal_state.omitIfMissing = true;
assert.equal(
validateProviderPackage(withOptionalRequiredState).errors.includes(
"mappingContract.gelios.units.to.fleet.positions.current.v5.fact.attributes.signal_state_required_but_mapping_can_omit",
),
true,
);
const withMalformedFieldContract = structuredClone(geliosProviderPackageV5);
withMalformedFieldContract.dataProducts[0].fieldContracts.signal_state = null;
assert.doesNotThrow(() => validateProviderPackage(withMalformedFieldContract));
assert.equal(validateProviderPackage(withMalformedFieldContract).ok, false);
const withUnboundedNumericMapping = structuredClone(geliosProviderPackageV5);
delete withUnboundedNumericMapping.mappingContracts[0].fact.attributes.speed_kph.minimum;
assert.equal(
validateProviderPackage(withUnboundedNumericMapping).errors.includes(
"mappingContract.gelios.units.to.fleet.positions.current.v5.fact.attributes.speed_kph.minimum_must_match_field_contract",
),
true,
);
const withNonOmittingBoundedMapping = structuredClone(geliosProviderPackageV5);
withNonOmittingBoundedMapping.mappingContracts[0].fact.attributes.course_degrees.omitIfInvalid = false;
assert.equal(
validateProviderPackage(withNonOmittingBoundedMapping).errors.includes(
"mappingContract.gelios.units.to.fleet.positions.current.v5.fact.attributes.course_degrees.bounded_number_must_omit_invalid",
),
true,
);
const canonicalMonitoringProduct = geliosProviderPackageV4.dataProducts[0];
const canonicalMonitoringMapping = geliosProviderPackageV4.mappingContracts[0];
const registeredCanonicalMonitoringProduct = JSON.parse(await readFile(new URL(
"../../../services/external-data-plane/definitions/fleet.positions.current.v3.json",
import.meta.url,
), "utf8"));
assert.equal(geliosProviderPackageV4.id, "gelios.provider.v4");
assert.equal(geliosProviderPackageV4.version, "4.0.0");
assert.deepEqual(geliosProviderPackageV4.manifest.ontology, {
packageId: "gelios",
revision: "ontology.gelios.v1_1",
});
assert.deepEqual(geliosProviderPackageV4.collectionProfiles[0].capabilityIds, [
"gelios.monitoring_config.current.read",
"gelios.units.current.read",
]);
assert.equal(
geliosProviderPackageV4.capabilities.find((item) => item.id === "gelios.monitoring_config.current.read").request.path,
"/api/v1/users/me/monitoring-config",
);
assert.equal(
geliosProviderPackageV4.capabilities.find((item) => item.id === "gelios.units.current.read").request.query.incltrip,
"true",
);
assert.deepEqual(canonicalMonitoringProduct, registeredCanonicalMonitoringProduct);
assert.deepEqual(canonicalMonitoringProduct.fields.filter((field) => field.endsWith("_state")), [
"movement_state",
"signal_state",
]);
for (const forbiddenField of [
"availability_state",
"freshness_state",
"operational_status",
"position_state",
"state_policy_version",
]) {
assert.equal(canonicalMonitoringProduct.fields.includes(forbiddenField), false);
}
assert.deepEqual(canonicalMonitoringMapping.derivations.signal_state.rules, [
"last_message_missing.inactive",
"last_message_age_lt_resolved_monitoring_limit.active",
"otherwise.inactive",
]);
assert.equal(canonicalMonitoringMapping.derivations.signal_state.default, "inactive");
assert.equal(canonicalMonitoringMapping.derivations.signal_state.parameters.activeDurationPath, "signalActiveDuration");
assert.equal(
canonicalMonitoringMapping.derivations.signal_state.parameters.somewhatInactiveDurationPath,
"signalSomewhatInactiveDuration",
);
assert.equal(canonicalMonitoringMapping.derivations.signal_state.parameters.collectionProfileFallbackSeconds, 120);
assert.equal(
canonicalMonitoringMapping.derivations.signal_state.parameters.thresholdResolution,
"somewhatInactive_then_active_then_profileFallback",
);
assert.equal(canonicalMonitoringMapping.derivations.movement_state.parameters.movingThresholdKph, 2);
assert.equal(canonicalMonitoringMapping.derivations.movement_state.default, "stopped");
assert.deepEqual(
geliosProviderPackageV4.l2Templates[0].steps.map((step) => step.kind),
[
"collection_trigger",
"provider_request",
"provider_request",
"extract_items",
"semantic_mapping",
"data_product_publish",
],
);
const stateAwareProduct = geliosProviderPackageV3.dataProducts[0];
const stateAwareMapping = geliosProviderPackageV3.mappingContracts[0];
const registeredStateAwareProduct = JSON.parse(await readFile(new URL(
"../../../services/external-data-plane/definitions/fleet.positions.current.v2.json",
import.meta.url,
), "utf8"));
assert.equal(geliosProviderPackageV3.id, "gelios.provider.v3");
assert.equal(geliosProviderPackageV3.version, "3.0.0");
assert.equal(geliosProviderPackageV3.authModes[0].id, "gelios.rest-rotating-bearer.v3");
assert.deepEqual(geliosProviderPackageV3.authModes[0].transport, {
placement: "header",
name: "Authorization",
});
assert.deepEqual(geliosProviderPackageV3.authModes[0].tokenLifecycle, {
artifacts: ["access", "refresh"],
requestArtifact: "access",
refreshMode: "runtime_managed",
});
assert.equal(geliosProviderPackageV3.capabilities[0].request.baseUrl, "https://api.geliospro.com");
assert.equal(geliosProviderPackageV3.capabilities[0].request.path, "/api/v1/units");
assert.deepEqual(geliosProviderPackageV3.capabilities[0].request.query, {});
assert.equal(
geliosProviderPackageV3.l2Templates[0].credentialBindings.find((binding) => binding.role === "provider").authModeId,
"gelios.rest-rotating-bearer.v3",
);
assert.equal(stateAwareProduct.id, "fleet.positions.current.v2");
assert.equal(stateAwareProduct.version, "2.0.0");
assert.equal(stateAwareProduct.ontologyRevision, "ontology.map.moving_object.v2");
assert.deepEqual(stateAwareProduct, registeredStateAwareProduct);
assert.deepEqual(
["availability_state", "freshness_state", "motion_state", "position_state"].map((field) => (
stateAwareMapping.fact.attributes[field]
)),
[
{ derive: "availability_state" },
{ derive: "freshness_state" },
{ derive: "motion_state" },
{ derive: "position_state" },
],
);
assert.equal(stateAwareMapping.fact.attributes.state_policy_version.constant, "map-moving-object-state/v1");
assert.equal(stateAwareMapping.derivations.motion_state.parameters.movingThresholdKph, 1);
assert.equal(stateAwareMapping.derivations.position_state.parameters.minSatelliteCount, 4);
assert.equal(stateAwareMapping.derivations.position_state.parameters.maxHdop, 5);
assert.equal(stateAwareMapping.derivations.position_state.parameters.maxHorizontalAccuracyMeters, 100);
const geliosSdkAuth = geliosProviderPackageV2.authModes[0];
const geliosSdkUnitsRead = geliosProviderPackageV2.capabilities[0];
@@ -318,7 +512,7 @@ for (const profile of withUnexecutedSecondCapability.collectionProfiles) {
}
assert.equal(
validateProviderPackage(withUnexecutedSecondCapability).errors.includes(
"collectionProfile.gelios.positions.current.realtime.v1.capabilityIds_must_select_one_v1_read",
"collectionProfile.gelios.positions.current.realtime.v1.template_capability_chain_mismatch",
),
true,
);