feat(data-plane): add provider contracts and ontology delivery
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { validateIntakeBatch } from "../../../packages/external-provider-contract/src/index.mjs";
|
||||
import {
|
||||
createWriterToken,
|
||||
hashWriterToken,
|
||||
materializeDataProductPublish,
|
||||
materializeWriterBoundBatch,
|
||||
normalizeWriterBindingRequest,
|
||||
safeWriterBinding,
|
||||
} from "../src/writer-binding.mjs";
|
||||
|
||||
const now = new Date("2026-07-15T12:00:00.000Z");
|
||||
const request = {
|
||||
source: {
|
||||
tenantId: "tenant-01",
|
||||
connectionId: "connection-01",
|
||||
providerId: "example-provider",
|
||||
},
|
||||
allowedDataProductIds: ["fleet.positions.current.v1"],
|
||||
expiresAt: "2026-08-01T12:00:00.000Z",
|
||||
};
|
||||
|
||||
const bindingPolicy = normalizeWriterBindingRequest(request, { now, maxTtlDays: 90 });
|
||||
assert.deepEqual(bindingPolicy, {
|
||||
tenantId: "tenant-01",
|
||||
connectionId: "connection-01",
|
||||
providerId: "example-provider",
|
||||
allowedDataProductIds: ["fleet.positions.current.v1"],
|
||||
expiresAt: "2026-08-01T12:00:00.000Z",
|
||||
});
|
||||
|
||||
const token = createWriterToken();
|
||||
assert.match(token, /^ndc_edpwb_[A-Za-z0-9_-]{40,}$/);
|
||||
assert.equal(hashWriterToken(token), hashWriterToken(token));
|
||||
assert.notEqual(hashWriterToken(token), hashWriterToken(`${token}x`));
|
||||
|
||||
const unscopedBatch = {
|
||||
schemaVersion: "nodedc.external-provider-contract/v1",
|
||||
source: { providerId: "example-provider" },
|
||||
contract: { dataProductId: "fleet.positions.current.v1", ontologyRevision: "example.v1", version: "1.0.0" },
|
||||
batch: { runId: "run-01", sequence: 0, idempotencyKey: "run-01.batch-0", receivedAt: "2026-07-15T12:00:00.000Z" },
|
||||
facts: [{ sourceId: "unit-01", semanticType: "map.moving_object", observedAt: "2026-07-15T12:00:00.000Z" }],
|
||||
};
|
||||
const bound = materializeWriterBoundBatch(unscopedBatch, { ...bindingPolicy, active: true }, { now });
|
||||
assert.deepEqual(bound.source, { providerId: "example-provider", tenantId: "tenant-01", connectionId: "connection-01" });
|
||||
assert.equal(validateIntakeBatch(bound).ok, true);
|
||||
assert.throws(() => materializeWriterBoundBatch({
|
||||
...unscopedBatch,
|
||||
source: { ...unscopedBatch.source, tenantId: "forged-tenant" },
|
||||
}, { ...bindingPolicy, active: true }, { now }), /writer_bound_scope_forbidden/);
|
||||
assert.throws(() => materializeWriterBoundBatch(unscopedBatch, { ...bindingPolicy, active: true }, {
|
||||
now,
|
||||
hasScopeHeaders: true,
|
||||
}), /writer_bound_scope_forbidden/);
|
||||
assert.throws(() => materializeWriterBoundBatch(unscopedBatch, {
|
||||
...bindingPolicy,
|
||||
providerId: "other-provider",
|
||||
active: true,
|
||||
}, { now }), /writer_binding_provider_forbidden/);
|
||||
assert.throws(() => materializeWriterBoundBatch({
|
||||
...unscopedBatch,
|
||||
contract: { ...unscopedBatch.contract, dataProductId: "other.product.v1" },
|
||||
}, { ...bindingPolicy, active: true }, { now }), /writer_binding_data_product_forbidden/);
|
||||
assert.throws(() => materializeWriterBoundBatch(unscopedBatch, { ...bindingPolicy, active: false }, { now }), /writer_binding_inactive/);
|
||||
|
||||
const materializedPublish = materializeDataProductPublish({
|
||||
schemaVersion: "nodedc.data-product.publish/v1",
|
||||
batch: { runId: "run-02", sequence: 0, idempotencyKey: "run-02.batch-0" },
|
||||
facts: unscopedBatch.facts,
|
||||
}, { ...bindingPolicy, active: true }, {
|
||||
id: "fleet.positions.current.v1",
|
||||
version: "1.0.0",
|
||||
ontologyRevision: "ontology.example-fleet.v1",
|
||||
}, "fleet.positions.current.v1", { now });
|
||||
assert.deepEqual(materializedPublish.source, {
|
||||
tenantId: "tenant-01",
|
||||
connectionId: "connection-01",
|
||||
providerId: "example-provider",
|
||||
});
|
||||
assert.equal(materializedPublish.batch.receivedAt, now.toISOString());
|
||||
assert.equal(materializedPublish.contract.version, "1.0.0");
|
||||
assert.equal(validateIntakeBatch(materializedPublish).ok, true);
|
||||
assert.throws(() => materializeDataProductPublish({
|
||||
schemaVersion: "nodedc.data-product.publish/v1",
|
||||
batch: { runId: "run-02", sequence: 0, idempotencyKey: "run-02.batch-0" },
|
||||
facts: unscopedBatch.facts,
|
||||
}, { ...bindingPolicy, active: true }, {
|
||||
id: "other.product.v1",
|
||||
version: "1.0.0",
|
||||
ontologyRevision: "ontology.example-fleet.v1",
|
||||
}, "other.product.v1", { now }), /writer_binding_data_product_forbidden/);
|
||||
|
||||
assert.throws(() => normalizeWriterBindingRequest({
|
||||
...request,
|
||||
expiresAt: "2027-01-01T00:00:00.000Z",
|
||||
}, { now, maxTtlDays: 90 }), /writer_binding_expiry_invalid/);
|
||||
assert.throws(() => normalizeWriterBindingRequest({
|
||||
...request,
|
||||
apiToken: "must-never-be-here",
|
||||
}, { now, maxTtlDays: 90 }), /writer_binding_request_secret_material_forbidden/);
|
||||
assert.throws(() => normalizeWriterBindingRequest({
|
||||
...request,
|
||||
arbitraryRuntimeSetting: "must-not-be-accepted",
|
||||
}, { now, maxTtlDays: 90 }), /writer_binding_request_fields_invalid/);
|
||||
|
||||
const safeBinding = safeWriterBinding({
|
||||
id: "binding-01",
|
||||
...bindingPolicy,
|
||||
active: true,
|
||||
createdAt: now,
|
||||
token: "must-not-leak",
|
||||
tokenHash: "must-not-leak",
|
||||
});
|
||||
assert.equal("token" in safeBinding, false);
|
||||
assert.equal("tokenHash" in safeBinding, false);
|
||||
|
||||
console.log("external-data-plane writer bindings: ok");
|
||||
Reference in New Issue
Block a user