NODEDC_PLATFORM/packages/external-provider-contract/test/contract.test.mjs

268 lines
12 KiB
JavaScript

import assert from "node:assert/strict";
import {
EXTERNAL_PROVIDER_CONTRACT_VERSION,
FOUNDRY_BINDING_UPSERT_SCHEMA_VERSION,
assertValid,
validateCollectionProfile,
validateConnectionProfile,
validateDataProduct,
validateFoundryBinding,
validateFoundryBindingUpsert,
validateIntakeBatch,
validateProviderManifest,
} from "../src/index.mjs";
import { geliosPositionsCurrentExample } from "../examples/gelios-positions-current.v1.mjs";
assert.equal(validateProviderManifest(geliosPositionsCurrentExample.providerManifest).ok, true);
assert.equal(validateConnectionProfile(geliosPositionsCurrentExample.connection).ok, true);
assert.equal(validateCollectionProfile(geliosPositionsCurrentExample.collectionProfile).ok, true);
assert.equal(validateDataProduct(geliosPositionsCurrentExample.dataProduct).ok, true);
assert.equal(validateFoundryBinding(geliosPositionsCurrentExample.foundryBinding).ok, true);
const foundryBindingUpsert = {
schemaVersion: FOUNDRY_BINDING_UPSERT_SCHEMA_VERSION,
applicationId: "11111111-1111-4111-8111-111111111111",
pageId: "map",
idempotencyKey: "foundry-binding-0123456789abcdef0123456789abcdef",
binding: {
id: "fleet-live-points",
dataProductId: "fleet.positions.current.v1",
slotId: "points",
semanticTypes: ["map.moving_object"],
fieldProjection: ["name", "speed", "course"],
},
};
assert.equal(validateFoundryBindingUpsert(foundryBindingUpsert).ok, true);
assert.equal(validateFoundryBindingUpsert({
...foundryBindingUpsert,
binding: { ...foundryBindingUpsert.binding, semanticTypes: ["map.moving_object", "map.moving_object"] },
}).errors.includes("binding.semanticTypes_must_not_contain_duplicates"), true);
assert.equal(validateFoundryBindingUpsert({
...foundryBindingUpsert,
binding: { ...foundryBindingUpsert.binding, accessToken: "forbidden" },
}).errors.includes("binding.accessToken_not_allowed"), true);
assert.equal(validateFoundryBindingUpsert({
...foundryBindingUpsert,
binding: { ...foundryBindingUpsert.binding, fieldProjection: ["ndc_edprb_forbidden-reader-token"] },
}).errors.includes("binding_must_not_contain_secret_material"), true);
const attributesWithSerializedSize = (size) => ({
blob: "x".repeat(size - Buffer.byteLength(JSON.stringify({ blob: "" }))),
});
const neutralIntakeBatch = {
schemaVersion: EXTERNAL_PROVIDER_CONTRACT_VERSION,
source: {
providerId: "example-provider",
tenantId: "sample-tenant",
connectionId: "sample-connection",
},
contract: {
dataProductId: "fleet.positions.current.v1",
ontologyRevision: "ontology.example-fleet.v1",
version: "1.0.0",
},
batch: {
runId: "run-20260714-001",
sequence: 0,
idempotencyKey: "run-20260714-001.batch-0",
receivedAt: "2026-07-14T18:00:00.000Z",
},
raw: {
contentType: "application/json",
hash: "sha256:example",
ref: "restricted://raw/run-20260714-001",
retentionDays: 14,
},
facts: [{
sourceId: "source-object-42",
semanticType: "map.moving_object",
observedAt: "2026-07-14T17:59:58.000Z",
geometry: { type: "Point", coordinates: [37.6173, 55.7558] },
attributes: { status: "active" },
}],
};
assert.equal(validateIntakeBatch(neutralIntakeBatch).ok, true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
raw: { contentType: "application/json", payload: { safe: "fixture" } },
}).errors.includes("raw.inline_payload_not_supported"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
raw: { contentType: "application/json", payload: "unsafe-unstructured-inline-raw" },
}).errors.includes("raw.inline_payload_not_supported"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
raw: { contentType: "application/json", payload: { providerAccessToken: "must-never-be-stored" } },
}).errors.includes("intake_must_not_contain_secret_material"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
facts: [{ ...neutralIntakeBatch.facts[0], attributes: { authorization: "Bearer must-never-be-stored" } }],
}).errors.includes("intake_must_not_contain_secret_material"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
facts: [{ ...neutralIntakeBatch.facts[0], attributes: { metadata: "ndc_edpwb_abcdefghijklmnopqrstuvwxyz0123456789ABCDE" } }],
}).errors.includes("intake_must_not_contain_secret_material"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
facts: [{ ...neutralIntakeBatch.facts[0], attributes: { metadata: "ndc_edprb_abcdefghijklmnopqrstuvwxyz0123456789ABCDE" } }],
}).errors.includes("intake_must_not_contain_secret_material"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
raw: { contentType: "application/json", hash: "prefix ndc_edpwb_abcdefghijklmnopqrstuvwxyz0123456789ABCDE suffix", ref: "restricted://raw/fixture" },
}).errors.includes("intake_must_not_contain_secret_material"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
facts: [{ ...neutralIntakeBatch.facts[0], attributes: { metadata: "Bearer opaque-secret-material" } }],
}).errors.includes("intake_must_not_contain_secret_material"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
raw: { contentType: "application/json", hash: "sha256:fixture", ref: "restricted://raw?access_token=must-never-be-stored" },
}).errors.includes("raw.ref_must_not_contain_secret_material"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
facts: [{ ...neutralIntakeBatch.facts[0], sourceId: "" }],
}).errors.includes("facts[0].sourceId_invalid"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
batch: { ...neutralIntakeBatch.batch, sequence: 2_147_483_647 },
}).ok, true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
batch: { ...neutralIntakeBatch.batch, sequence: 2_147_483_648 },
}).errors.includes("batch.sequence_must_be_integer_0_to_2147483647"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
facts: [{ ...neutralIntakeBatch.facts[0], attributes: attributesWithSerializedSize(64 * 1024) }],
}).ok, true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
facts: [{ ...neutralIntakeBatch.facts[0], attributes: attributesWithSerializedSize((64 * 1024) + 1) }],
}).errors.includes("facts[0].attributes_size_exceeded"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
facts: [{ ...neutralIntakeBatch.facts[0], geometry: { type: "Point", coordinates: [180.0001, 55.7558] } }],
}).errors.includes("facts[0].geometry.longitude_out_of_range"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
facts: [{ ...neutralIntakeBatch.facts[0], geometry: { type: "Point", coordinates: [37.6173, -90.0001] } }],
}).errors.includes("facts[0].geometry.latitude_out_of_range"), true);
assert.equal(validateIntakeBatch({
...neutralIntakeBatch,
debug: true,
}).errors.includes("intakeBatch.debug_not_allowed"), true);
assert.equal(validateConnectionProfile({
...geliosPositionsCurrentExample.connection,
apiToken: "must-never-be-here",
}).ok, false);
assert.equal(validateConnectionProfile({
...geliosPositionsCurrentExample.connection,
credentialRef: {
...geliosPositionsCurrentExample.connection.credentialRef,
reference: "ndc_edpwb_not-allowed-even-in-a-non-secret-field",
},
}).errors.includes("profile_must_not_contain_secret_material"), true);
assert.equal(validateConnectionProfile({
...geliosPositionsCurrentExample.connection,
credentialRef: {
...geliosPositionsCurrentExample.connection.credentialRef,
reference: "opaque-reference?access_token=must-not-cross-the-boundary",
},
}).errors.includes("profile_must_not_contain_secret_material"), true);
assert.equal(validateConnectionProfile({
...geliosPositionsCurrentExample.connection,
credentialRef: { ...geliosPositionsCurrentExample.connection.credentialRef, namespace: "unexpected" },
}).errors.includes("credentialRef.namespace_not_allowed"), true);
assert.equal(validateConnectionProfile({
...geliosPositionsCurrentExample.connection,
scope: { ...geliosPositionsCurrentExample.connection.scope, providerSelector: "unexpected" },
}).errors.includes("scope.providerSelector_not_allowed"), true);
assert.equal(validateCollectionProfile({
...geliosPositionsCurrentExample.collectionProfile,
mode: "manual",
}).errors.includes("manual_profile_must_not_define_intervalMs"), true);
assert.equal(validateCollectionProfile({
...geliosPositionsCurrentExample.collectionProfile,
schedule: { intervalMs: 3000, jitterMs: 100 },
}).errors.includes("schedule.jitterMs_not_allowed"), true);
assert.equal(validateCollectionProfile({
...geliosPositionsCurrentExample.collectionProfile,
capabilityIds: ["ndc_edprb_forbidden-reader-token"],
}).errors.includes("collectionProfile_must_not_contain_secret_material"), true);
assert.equal(validateFoundryBinding({
...geliosPositionsCurrentExample.foundryBinding,
providerId: "gelios",
}).errors.includes("binding_must_reference_data_product_not_provider_transport"), true);
assert.equal(validateFoundryBinding({
...geliosPositionsCurrentExample.foundryBinding,
applicationId: undefined,
}).errors.includes("applicationId_invalid"), true);
assert.equal(validateFoundryBinding({
...geliosPositionsCurrentExample.foundryBinding,
pageId: undefined,
}).errors.includes("pageId_invalid"), true);
assert.equal(validateFoundryBinding({
...geliosPositionsCurrentExample.foundryBinding,
templateId: undefined,
}).ok, true);
assert.equal(validateFoundryBinding({
...geliosPositionsCurrentExample.foundryBinding,
rendererOptions: {},
}).errors.includes("foundryBinding.rendererOptions_not_allowed"), true);
assert.equal(validateFoundryBinding({
...geliosPositionsCurrentExample.foundryBinding,
semanticType: "ndc_edprb_forbidden-reader-token",
}).errors.includes("binding_must_not_contain_secret_material"), true);
assert.equal(validateProviderManifest({
...geliosPositionsCurrentExample.providerManifest,
tenantId: "must-not-live-in-provider-manifest",
}).errors.includes("manifest_must_not_contain_connection_runtime_state"), true);
assert.equal(validateProviderManifest({
...geliosPositionsCurrentExample.providerManifest,
apiToken: "must-never-be-here",
}).errors.includes("manifest_must_not_contain_secret_material"), true);
assert.equal(validateProviderManifest({
...geliosPositionsCurrentExample.providerManifest,
endpoint: "https://must-live-in-l2-template.invalid",
}).errors.includes("manifest_must_not_contain_provider_transport"), true);
assert.equal(validateProviderManifest({
...geliosPositionsCurrentExample.providerManifest,
capabilities: [{ id: "gelios.units.current.read", classification: "not-a-class" }],
}).errors.includes("capabilities[0].classification_invalid"), true);
assert.equal(validateProviderManifest({
...geliosPositionsCurrentExample.providerManifest,
metadata: {},
}).errors.includes("providerManifest.metadata_not_allowed"), true);
assert.equal(validateProviderManifest({
...geliosPositionsCurrentExample.providerManifest,
ontology: { ...geliosPositionsCurrentExample.providerManifest.ontology, transport: "unexpected" },
}).errors.includes("ontology.transport_not_allowed"), true);
assert.equal(validateProviderManifest({
...geliosPositionsCurrentExample.providerManifest,
capabilities: [{ id: "gelios.units.current.read", classification: "read", endpoint: "/units" }],
}).errors.includes("capabilities[0].endpoint_not_allowed"), true);
assert.equal(validateProviderManifest({
...geliosPositionsCurrentExample.providerManifest,
dataProductIds: ["ndc_edpwb_forbidden-writer-token"],
}).errors.includes("manifest_must_not_contain_secret_material"), true);
assert.equal(validateDataProduct({
...geliosPositionsCurrentExample.dataProduct,
delivery: { mode: "snapshot+patch", transport: "sse" },
}).errors.includes("delivery.transport_not_allowed"), true);
assert.throws(() => assertValid(validateDataProduct, {
schemaVersion: EXTERNAL_PROVIDER_CONTRACT_VERSION,
id: "fleet.positions.current.v1",
version: "1.0.0",
delivery: { mode: "snapshot" },
semanticTypes: [],
fields: [],
access: { audience: "public" },
}));
console.log("external-provider-contract: ok");