import assert from "node:assert/strict";
import { spawn } from "node:child_process";
import { createHash, generateKeyPairSync, randomBytes, sign } from "node:crypto";
import { mkdtemp, rm, writeFile } from "node:fs/promises";
import net from "node:net";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { validateDataProductHistory, validateDataProductPatch, validateDataProductSnapshot } from "@nodedc/external-provider-contract/data-plane";
import {
  MANAGED_PROVISIONER_HEADERS,
  managedProvisionerSigningPayload,
  sha256RawBody,
} from "../src/managed-provisioner-auth.mjs";

const databaseUrl = process.env.EXTERNAL_DATA_PLANE_TEST_DATABASE_URL;
if (!databaseUrl) throw new Error("EXTERNAL_DATA_PLANE_TEST_DATABASE_URL_required");
const port = await freePort();
const baseUrl = `http://127.0.0.1:${port}`;
const directory = await mkdtemp(join(tmpdir(), "nodedc-edp-api-test-"));
const provisionerSecret = "nodedc_edp_integration_provisioner_secret_0123456789abcdef";
const secretPath = join(directory, "provisioner-token");
const managedProvisionerServiceId = "nodedc-engine";
const managedProvisionerKeyId = "engine-edp-managed-provisioner-v1";
const managedProvisionerAudience = "nodedc-external-data-plane.managed-provisioning.v1";
const managedProvisionerPublicKeyPath = join(directory, "engine-public-key.pem");
const { privateKey: managedProvisionerPrivateKey, publicKey: managedProvisionerPublicKey } = generateKeyPairSync("ed25519");
const foundryProvisionerServiceId = "nodedc-module-foundry";
const foundryProvisionerKeyId = "foundry-edp-managed-provisioner-v1";
const foundryProvisionerAudience = "nodedc-external-data-plane.managed-provisioning.v1";
const foundryProvisionerPublicKeyPath = join(directory, "foundry-public-key.pem");
const { privateKey: foundryProvisionerPrivateKey, publicKey: foundryProvisionerPublicKey } = generateKeyPairSync("ed25519");
await writeFile(secretPath, `${provisionerSecret}\n`, { mode: 0o600 });
await writeFile(
  managedProvisionerPublicKeyPath,
  managedProvisionerPublicKey.export({ type: "spki", format: "pem" }),
  { mode: 0o600 },
);
await writeFile(
  foundryProvisionerPublicKeyPath,
  foundryProvisionerPublicKey.export({ type: "spki", format: "pem" }),
  { mode: 0o600 },
);

const child = spawn(process.execPath, ["src/server.mjs"], {
  cwd: new URL("..", import.meta.url),
  env: {
    ...process.env,
    PORT: String(port),
    EXTERNAL_DATA_PLANE_DATABASE_URL: databaseUrl,
    EXTERNAL_DATA_PLANE_PROVISIONING_ENABLED: "true",
    EXTERNAL_DATA_PLANE_MANAGED_PROVISIONING_ENABLED: "true",
    EXTERNAL_DATA_PLANE_PROVISIONER_TOKEN_FILE: secretPath,
    EXTERNAL_DATA_PLANE_MANAGED_PROVISIONER_PUBLIC_KEY_FILE: managedProvisionerPublicKeyPath,
    EXTERNAL_DATA_PLANE_MANAGED_PROVISIONER_SERVICE_ID: managedProvisionerServiceId,
    EXTERNAL_DATA_PLANE_MANAGED_PROVISIONER_KEY_ID: managedProvisionerKeyId,
    EXTERNAL_DATA_PLANE_MANAGED_PROVISIONER_AUDIENCE: managedProvisionerAudience,
    EXTERNAL_DATA_PLANE_FOUNDRY_PROVISIONING_ENABLED: "true",
    EXTERNAL_DATA_PLANE_FOUNDRY_PROVISIONER_PUBLIC_KEY_FILE: foundryProvisionerPublicKeyPath,
    EXTERNAL_DATA_PLANE_FOUNDRY_PROVISIONER_SERVICE_ID: foundryProvisionerServiceId,
    EXTERNAL_DATA_PLANE_FOUNDRY_PROVISIONER_KEY_ID: foundryProvisionerKeyId,
    EXTERNAL_DATA_PLANE_FOUNDRY_PROVISIONER_AUDIENCE: foundryProvisionerAudience,
    EXTERNAL_DATA_PLANE_RETENTION_SWEEP_MS: "60000",
    EXTERNAL_DATA_PLANE_STREAM_POLL_MS: "250",
    EXTERNAL_DATA_PLANE_STREAM_HEARTBEAT_MS: "5000",
  },
  stdio: ["ignore", "pipe", "pipe"],
});
let childOutput = "";
child.stdout.on("data", (chunk) => { childOutput += chunk.toString(); });
child.stderr.on("data", (chunk) => { childOutput += chunk.toString(); });

try {
  await waitForHealth();
  const productId = "api.test.positions.v1";
  const product = await jsonRequest(`/internal/data-plane/v1/data-products/${productId}`, {
    method: "PUT",
    token: provisionerSecret,
    body: {
      version: "1.0.0",
      ontologyRevision: "ontology.api.test.v1",
      deliveryMode: "snapshot+patch",
      semanticTypes: ["map.moving_object"],
      fields: ["source_id", "observed_at", "geometry", "status"],
      history: { mode: "sampled", intervalMs: 60_000, strategy: "latest-per-entity-per-bucket", retentionDays: 30 },
    },
  });
  assert.equal(product.dataProduct.id, productId);

  const expiry = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
  const scope = { tenantId: "api-tenant", connectionId: "api-connection", providerId: "api-provider" };
  const managedToken = "ndc_edpwb_managed_api_test_0123456789abcdefghijklmnopqrstuvwxyz";
  const managedBody = {
    source: scope,
    allowedDataProductIds: [productId],
    expiresAt: null,
    generation: 1,
    capabilityDigest: createHash("sha256").update(managedToken, "utf8").digest("hex"),
  };
  const managedPath = "/internal/data-plane/v1/writer-bindings/by-key/engine.api-connection.positions";
  const bearerOnlyManaged = await fetch(`${baseUrl}${managedPath}`, {
    method: "PUT",
    headers: { Authorization: `Bearer ${provisionerSecret}`, "Content-Type": "application/json" },
    body: JSON.stringify(managedBody),
  });
  assert.equal(bearerOnlyManaged.status, 401);
  assert.equal((await bearerOnlyManaged.json()).error, "managed_provisioner_header_invalid");

  const managedResults = await Promise.all([
    rawJsonRequest(managedPath, {
      method: "PUT",
      managedSignature: true,
      body: managedBody,
    }),
    rawJsonRequest(managedPath, {
      method: "PUT",
      managedSignature: true,
      body: managedBody,
    }),
  ]);
  assert.deepEqual(managedResults.map(({ value }) => value.idempotent).sort(), [false, true]);
  assert.equal(managedResults[0].value.writerBinding.id, managedResults[1].value.writerBinding.id);
  assert.equal("token" in managedResults[0].value, false);
  assert.equal(JSON.stringify(managedResults[0].value).includes(managedBody.capabilityDigest), false);
  const managedCatalog = await jsonRequest("/internal/data-plane/v1/writer/data-products", { token: managedToken });
  assert.deepEqual(managedCatalog.dataProducts.map((value) => value.id), [productId]);
  const replayBody = JSON.stringify(managedBody);
  const replayHeaders = signedManagedHeaders(managedPath, "PUT", Buffer.from(replayBody, "utf8"));
  const firstReplayAttempt = await fetch(`${baseUrl}${managedPath}`, {
    method: "PUT", headers: { ...replayHeaders, "Content-Type": "application/json" }, body: replayBody,
  });
  assert.equal(firstReplayAttempt.status, 200);
  const rejectedReplay = await fetch(`${baseUrl}${managedPath}`, {
    method: "PUT", headers: { ...replayHeaders, "Content-Type": "application/json" }, body: replayBody,
  });
  assert.equal(rejectedReplay.status, 409);
  assert.equal((await rejectedReplay.json()).error, "managed_provisioner_request_replayed");

  const tamperHeaders = signedManagedHeaders(managedPath, "PUT", Buffer.from(replayBody, "utf8"));
  const tamperedBody = await fetch(`${baseUrl}${managedPath}`, {
    method: "PUT",
    headers: { ...tamperHeaders, "Content-Type": "application/json" },
    body: `${replayBody} `,
  });
  assert.equal(tamperedBody.status, 401);
  assert.equal((await tamperedBody.json()).error, "managed_provisioner_body_hash_mismatch");

  const pathHeaders = signedManagedHeaders(managedPath, "PUT", Buffer.from(replayBody, "utf8"));
  const tamperedPath = await fetch(`${baseUrl}${managedPath}?unexpected=true`, {
    method: "PUT", headers: { ...pathHeaders, "Content-Type": "application/json" }, body: replayBody,
  });
  assert.equal(tamperedPath.status, 401);
  assert.equal((await tamperedPath.json()).error, "managed_provisioner_signature_invalid");

  const audienceHeaders = signedManagedHeaders(managedPath, "PUT", Buffer.from(replayBody, "utf8"));
  audienceHeaders[MANAGED_PROVISIONER_HEADERS.audience] = "other-audience";
  const wrongAudience = await fetch(`${baseUrl}${managedPath}`, {
    method: "PUT", headers: { ...audienceHeaders, "Content-Type": "application/json" }, body: replayBody,
  });
  assert.equal(wrongAudience.status, 401);
  assert.equal((await wrongAudience.json()).error, "managed_provisioner_identity_mismatch");

  const managedConflict = await signedFetch(managedPath, {
    method: "PUT",
    body: {
      ...managedBody,
      capabilityDigest: createHash("sha256").update(`${managedToken}-different`, "utf8").digest("hex"),
    },
  });
  assert.equal(managedConflict.status, 409);
  assert.equal((await managedConflict.json()).error, "managed_writer_binding_request_conflict");

  const legacyManagedRevoke = await fetch(
    `${baseUrl}/internal/data-plane/v1/writer-bindings/${managedResults[0].value.writerBinding.id}/revoke`,
    { method: "POST", headers: { Authorization: `Bearer ${provisionerSecret}` } },
  );
  assert.equal(legacyManagedRevoke.status, 404);

  const managedTokenGeneration2 = `${managedToken}_generation_2`;
  const managedGeneration2 = await jsonRequest(
    "/internal/data-plane/v1/writer-bindings/by-key/engine.api-connection.positions",
    {
      method: "PUT",
      managedSignature: true,
      body: {
        ...managedBody,
        generation: 2,
        capabilityDigest: createHash("sha256").update(managedTokenGeneration2, "utf8").digest("hex"),
      },
    },
  );
  assert.equal(managedGeneration2.writerBinding.generation, 2);
  assert.deepEqual(
    (await jsonRequest("/internal/data-plane/v1/writer/data-products", { token: managedTokenGeneration2 })).dataProducts.map((value) => value.id),
    [productId],
  );
  const managedRevoke = await jsonRequest(
    "/internal/data-plane/v1/writer-bindings/by-key/engine.api-connection.positions/generations/1/revoke",
    { method: "POST", managedSignature: true },
  );
  assert.equal(managedRevoke.idempotent, false);
  assert.equal(managedRevoke.writerBinding.active, false);
  const managedRevokeRetry = await jsonRequest(
    "/internal/data-plane/v1/writer-bindings/by-key/engine.api-connection.positions/generations/1/revoke",
    { method: "POST", managedSignature: true },
  );
  assert.equal(managedRevokeRetry.idempotent, true);
  const rejectedManagedGeneration1 = await fetch(`${baseUrl}/internal/data-plane/v1/writer/data-products`, {
    headers: { Authorization: `Bearer ${managedToken}` },
  });
  assert.equal(rejectedManagedGeneration1.status, 401);

  const managedReaderToken = "ndc_edprb_managed_api_test_0123456789abcdefghijklmnopqrstuvwxyz";
  const managedReaderBody = {
    source: { ...scope, connectionId: "api-consumer-connection" },
    allowedDataProductIds: [productId],
    expiresAt: null,
    generation: 1,
    capabilityDigest: createHash("sha256").update(managedReaderToken, "utf8").digest("hex"),
  };
  const managedReaderPath = "/internal/data-plane/v1/reader-bindings/by-key/engine.api-connection.positions-reader";
  const managedReaderResults = await Promise.all([
    rawJsonRequest(managedReaderPath, { method: "PUT", managedSignature: true, body: managedReaderBody }),
    rawJsonRequest(managedReaderPath, { method: "PUT", managedSignature: true, body: managedReaderBody }),
  ]);
  assert.deepEqual(managedReaderResults.map(({ value }) => value.idempotent).sort(), [false, true]);
  assert.equal(managedReaderResults[0].value.readerBinding.id, managedReaderResults[1].value.readerBinding.id);
  assert.equal(managedReaderResults[0].value.readerBinding.connectionId, "api-consumer-connection");
  assert.equal("token" in managedReaderResults[0].value, false);
  assert.equal(JSON.stringify(managedReaderResults[0].value).includes(managedReaderBody.capabilityDigest), false);
  assert.deepEqual(
    (await jsonRequest("/internal/data-plane/v1/reader/data-products", { token: managedReaderToken })).dataProducts.map((value) => value.id),
    [productId],
  );
  const managedSourcePublish = await jsonRequest(`/internal/data-plane/v1/data-products/${productId}/publish`, {
    method: "POST",
    token: managedTokenGeneration2,
    body: publish("api-managed-reader-source", "2026-07-15T11:00:00.000Z", 37.60),
  });
  assert.equal(managedSourcePublish.currentUpdatedCount, 1);
  const managedReaderSnapshot = await jsonRequest(
    `/internal/data-plane/v1/data-products/${productId}/snapshot`,
    { token: managedReaderToken },
  );
  assert.equal(validateDataProductSnapshot(managedReaderSnapshot).ok, true);
  assert.equal(managedReaderSnapshot.facts.length, 1);
  const legacyManagedReaderRevoke = await fetch(
    `${baseUrl}/internal/data-plane/v1/reader-bindings/${managedReaderResults[0].value.readerBinding.id}/revoke`,
    { method: "POST", headers: { Authorization: `Bearer ${provisionerSecret}` } },
  );
  assert.equal(legacyManagedReaderRevoke.status, 404);
  const managedReaderRevoke = await jsonRequest(
    `${managedReaderPath}/generations/1/revoke`,
    { method: "POST", managedSignature: true },
  );
  assert.equal(managedReaderRevoke.idempotent, false);
  assert.equal(managedReaderRevoke.readerBinding.active, false);
  const managedReaderRevokeRetry = await jsonRequest(
    `${managedReaderPath}/generations/1/revoke`,
    { method: "POST", managedSignature: true },
  );
  assert.equal(managedReaderRevokeRetry.idempotent, true);
  const rejectedManagedReader = await fetch(`${baseUrl}/internal/data-plane/v1/reader/data-products`, {
    headers: { Authorization: `Bearer ${managedReaderToken}` },
  });
  assert.equal(rejectedManagedReader.status, 401);

  const foundryPlanPath = "/internal/data-plane/v1/consumer-reader-bindings/plan";
  const foundryPlanBody = { allowedDataProductIds: [productId] };
  const engineCannotProvisionFoundryGrant = await signedFetch(foundryPlanPath, {
    method: "POST",
    body: foundryPlanBody,
  });
  assert.equal(engineCannotProvisionFoundryGrant.status, 401);
  assert.equal((await engineCannotProvisionFoundryGrant.json()).error, "managed_provisioner_identity_mismatch");
  const foundryPlan = await jsonRequest(foundryPlanPath, {
    method: "POST",
    foundrySignature: true,
    body: foundryPlanBody,
  });
  assert.equal(foundryPlan.sourceScope, "resolved-server-side");
  assert.deepEqual(foundryPlan.dataProducts.map((value) => value.id), [productId]);
  assert.equal(/tenant|provider|connection/i.test(JSON.stringify(foundryPlan)), false);

  const foundryReaderToken = "ndc_edprb_foundry_api_test_0123456789abcdefghijklmnopqrstuvwxyz";
  const foundryReaderBody = {
    allowedDataProductIds: [productId],
    expiresAt: null,
    generation: 1,
    capabilityDigest: createHash("sha256").update(foundryReaderToken, "utf8").digest("hex"),
  };
  const foundryReaderPath = "/internal/data-plane/v1/consumer-reader-bindings/by-key/fndrc-api-test-positions";
  const foundryReaderResults = await Promise.all([
    rawJsonRequest(foundryReaderPath, { method: "PUT", foundrySignature: true, body: foundryReaderBody }),
    rawJsonRequest(foundryReaderPath, { method: "PUT", foundrySignature: true, body: foundryReaderBody }),
  ]);
  assert.deepEqual(foundryReaderResults.map(({ value }) => value.idempotent).sort(), [false, true]);
  assert.equal(foundryReaderResults[0].value.readerBinding.id, foundryReaderResults[1].value.readerBinding.id);
  assert.equal(JSON.stringify(foundryReaderResults[0].value).includes(foundryReaderBody.capabilityDigest), false);
  assert.equal(/tenant|provider|connection/i.test(JSON.stringify(foundryReaderResults[0].value)), false);
  assert.equal("token" in foundryReaderResults[0].value, false);
  const foundrySnapshot = await jsonRequest(
    `/internal/data-plane/v1/data-products/${productId}/snapshot`,
    { token: foundryReaderToken },
  );
  assert.equal(validateDataProductSnapshot(foundrySnapshot).ok, true);
  assert.equal(foundrySnapshot.facts.length, 1);
  const foundryRevoke = await jsonRequest(`${foundryReaderPath}/generations/1/revoke`, {
    method: "POST",
    foundrySignature: true,
  });
  assert.equal(foundryRevoke.idempotent, false);
  assert.equal(foundryRevoke.readerBinding.active, false);
  const foundryRevokeRetry = await jsonRequest(`${foundryReaderPath}/generations/1/revoke`, {
    method: "POST",
    foundrySignature: true,
  });
  assert.equal(foundryRevokeRetry.idempotent, true);
  const rejectedFoundryReader = await fetch(`${baseUrl}/internal/data-plane/v1/reader/data-products`, {
    headers: { Authorization: `Bearer ${foundryReaderToken}` },
  });
  assert.equal(rejectedFoundryReader.status, 401);

  const secondWriterToken = "ndc_edpwb_second_source_api_test_0123456789abcdefghijklmnopqrstuvwxyz";
  await jsonRequest("/internal/data-plane/v1/writer-bindings/by-key/engine.api-connection-2.positions", {
    method: "PUT",
    managedSignature: true,
    body: {
      ...managedBody,
      source: { ...scope, connectionId: "api-connection-2" },
      capabilityDigest: createHash("sha256").update(secondWriterToken, "utf8").digest("hex"),
    },
  });
  const ambiguousFoundryPlan = await foundrySignedFetch(foundryPlanPath, {
    method: "POST",
    body: foundryPlanBody,
  });
  assert.equal(ambiguousFoundryPlan.status, 409);
  assert.equal((await ambiguousFoundryPlan.json()).error, "managed_consumer_reader_source_scope_ambiguous");
  const ambiguousReaderToken = "ndc_edprb_ambiguous_api_test_0123456789abcdefghijklmnopqrstuvwxyz";
  const ambiguousReader = await signedFetch(
    "/internal/data-plane/v1/reader-bindings/by-key/engine.api-ambiguous.positions-reader",
    {
      method: "PUT",
      body: {
        ...managedReaderBody,
        source: { ...scope, connectionId: "api-other-consumer" },
        capabilityDigest: createHash("sha256").update(ambiguousReaderToken, "utf8").digest("hex"),
      },
    },
  );
  assert.equal(ambiguousReader.status, 409);
  assert.equal((await ambiguousReader.json()).error, "managed_reader_source_scope_ambiguous");

  const manualWriterBody = { source: scope, allowedDataProductIds: [productId], expiresAt: expiry };
  const signedOnlyManualProvisioning = await signedFetch("/internal/data-plane/v1/writer-bindings", {
    method: "POST",
    body: manualWriterBody,
  });
  assert.equal(signedOnlyManualProvisioning.status, 401);
  assert.equal((await signedOnlyManualProvisioning.json()).error, "provisioner_unauthorized");

  const writerIssuance = await rawJsonRequest("/internal/data-plane/v1/writer-bindings", {
    method: "POST",
    token: provisionerSecret,
    body: manualWriterBody,
  });
  const readerIssuance = await rawJsonRequest("/internal/data-plane/v1/reader-bindings", {
    method: "POST",
    token: provisionerSecret,
    body: { source: scope, allowedDataProductIds: [productId], expiresAt: expiry },
  });
  assertOneTimeCapabilityResponse(writerIssuance.response);
  assertOneTimeCapabilityResponse(readerIssuance.response);
  const writer = writerIssuance.value;
  const reader = readerIssuance.value;
  assert.equal(typeof writer.token, "string");
  assert.equal(typeof reader.token, "string");

  const catalog = await jsonRequest("/internal/data-plane/v1/writer/data-products", { token: writer.token });
  assert.deepEqual(catalog.dataProducts.map((value) => value.id), [productId]);

  const first = await jsonRequest(`/internal/data-plane/v1/data-products/${productId}/publish`, {
    method: "POST",
    token: writer.token,
    body: publish("api-run-01", "2026-07-15T12:00:00.000Z", 37.61),
  });
  assert.equal(first.currentUpdatedCount, 1);
  const duplicate = await jsonRequest(`/internal/data-plane/v1/data-products/${productId}/publish`, {
    method: "POST",
    token: writer.token,
    body: publish("api-run-01", "2026-07-15T12:00:00.000Z", 37.61),
  });
  assert.equal(duplicate.idempotent, true);
  const reusedKey = await fetch(`${baseUrl}/internal/data-plane/v1/data-products/${productId}/publish`, {
    method: "POST",
    headers: { Authorization: `Bearer ${writer.token}`, "Content-Type": "application/json" },
    body: JSON.stringify(publish("api-run-01", "2026-07-15T12:00:00.000Z", 99.9)),
  });
  assert.equal(reusedKey.status, 409);
  assert.equal((await reusedKey.json()).error, "idempotency_key_reused");

  const snapshot = await jsonRequest(`/internal/data-plane/v1/data-products/${productId}/snapshot`, { token: reader.token });
  assert.equal(validateDataProductSnapshot(snapshot).ok, true);
  assert.equal(snapshot.facts.length, 1);
  const history = await jsonRequest(
    `/internal/data-plane/v1/data-products/${productId}/history?from=2026-07-15T12%3A00%3A00.000Z&to=2026-07-15T12%3A02%3A00.000Z&resolutionMs=60000&sourceIds=unit-01&limit=100`,
    { token: reader.token },
  );
  assert.equal(validateDataProductHistory(history).ok, true);
  assert.equal(history.facts.length, 1);
  assert.equal(history.facts[0].bucketStart, "2026-07-15T12:00:00.000Z");

  const controller = new AbortController();
  const response = await fetch(`${baseUrl}/internal/data-plane/v1/data-products/${productId}/stream?after=${snapshot.cursor}`, {
    headers: { Authorization: `Bearer ${reader.token}` },
    signal: controller.signal,
  });
  assert.equal(response.status, 200);
  const patchPromise = readFirstPatch(response, controller);
  await jsonRequest(`/internal/data-plane/v1/data-products/${productId}/publish`, {
    method: "POST",
    token: writer.token,
    body: publish("api-run-02", "2026-07-15T12:00:10.000Z", 37.62),
  });
  const patch = await patchPromise;
  assert.equal(validateDataProductPatch(patch).ok, true);
  assert.equal(patch.previousCursor, snapshot.cursor);

  const forbidden = await fetch(`${baseUrl}/internal/data-plane/v1/data-products/${productId}/snapshot`, {
    headers: {
      Authorization: `Bearer ${reader.token}`,
      "X-NODEDC-Tenant-Id": scope.tenantId,
      "X-NODEDC-Connection-Id": scope.connectionId,
    },
  });
  assert.equal(forbidden.status, 400);

  const revocationSnapshot = await jsonRequest(`/internal/data-plane/v1/data-products/${productId}/snapshot`, { token: reader.token });
  const revocationStream = await fetch(`${baseUrl}/internal/data-plane/v1/data-products/${productId}/stream?after=${revocationSnapshot.cursor}`, {
    headers: { Authorization: `Bearer ${reader.token}` },
  });
  assert.equal(revocationStream.status, 200);
  const revokedEventPromise = readNamedEvent(revocationStream, "error");
  const rotatedReaderIssuance = await rawJsonRequest(`/internal/data-plane/v1/reader-bindings/${reader.readerBinding.id}/rotate`, {
    method: "POST",
    token: provisionerSecret,
  });
  assertOneTimeCapabilityResponse(rotatedReaderIssuance.response);
  const rotatedReader = rotatedReaderIssuance.value;
  const revokedEvent = await revokedEventPromise;
  assert.equal(revokedEvent.error, "reader_stream_access_revoked");
  const rejectedOldReader = await fetch(`${baseUrl}/internal/data-plane/v1/data-products/${productId}/snapshot`, {
    headers: { Authorization: `Bearer ${reader.token}` },
  });
  assert.equal(rejectedOldReader.status, 401);
  const rotatedSnapshot = await jsonRequest(`/internal/data-plane/v1/data-products/${productId}/snapshot`, { token: rotatedReader.token });
  assert.equal(rotatedSnapshot.dataProduct.id, productId);

  const shutdownStream = await fetch(`${baseUrl}/internal/data-plane/v1/data-products/${productId}/stream?after=${rotatedSnapshot.cursor}`, {
    headers: { Authorization: `Bearer ${rotatedReader.token}` },
  });
  assert.equal(shutdownStream.status, 200);
  child.kill("SIGTERM");
  assert.equal(await waitForChildExit(child, 3_000), true);

  console.log("external-data-plane API integration: ok");
} catch (error) {
  error.message = `${error.message}\nserver_output=${childOutput.replace(/[A-Za-z0-9_-]{48,}/g, "[redacted]").slice(-4000)}`;
  throw error;
} finally {
  child.kill("SIGTERM");
  await Promise.race([
    new Promise((resolve) => child.once("exit", resolve)),
    new Promise((resolve) => setTimeout(resolve, 3000)),
  ]);
  await rm(directory, { recursive: true, force: true });
}

function publish(runId, observedAt, longitude) {
  return {
    schemaVersion: "nodedc.data-product.publish/v1",
    batch: { runId, sequence: 0, idempotencyKey: `${runId}.chunk-0` },
    facts: [{
      sourceId: "unit-01",
      semanticType: "map.moving_object",
      observedAt,
      attributes: { status: "online" },
      geometry: { type: "Point", coordinates: [longitude, 55.75] },
    }],
  };
}

async function jsonRequest(path, { method = "GET", token, managedSignature = false, foundrySignature = false, body } = {}) {
  const { response, value } = await rawJsonRequest(path, { method, token, managedSignature, foundrySignature, body });
  if (!response.ok) throw new Error(`request_failed:${response.status}:${value.error}`);
  return value;
}

async function rawJsonRequest(path, { method = "GET", token, managedSignature = false, foundrySignature = false, body } = {}) {
  const rawBody = body === undefined ? Buffer.alloc(0) : Buffer.from(JSON.stringify(body), "utf8");
  const response = await fetch(`${baseUrl}${path}`, {
    method,
    headers: {
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...(managedSignature ? signedManagedHeaders(path, method, rawBody) : {}),
      ...(foundrySignature ? signedFoundryHeaders(path, method, rawBody) : {}),
      ...(body === undefined ? {} : { "Content-Type": "application/json" }),
    },
    body: body === undefined ? undefined : rawBody,
  });
  const value = await response.json();
  if (!response.ok) throw new Error(`request_failed:${response.status}:${value.error}`);
  return { response, value };
}

async function signedFetch(path, { method, body } = {}) {
  const rawBody = body === undefined ? Buffer.alloc(0) : Buffer.from(JSON.stringify(body), "utf8");
  return fetch(`${baseUrl}${path}`, {
    method,
    headers: {
      ...signedManagedHeaders(path, method, rawBody),
      ...(body === undefined ? {} : { "Content-Type": "application/json" }),
    },
    body: body === undefined ? undefined : rawBody,
  });
}

async function foundrySignedFetch(path, { method, body } = {}) {
  const rawBody = body === undefined ? Buffer.alloc(0) : Buffer.from(JSON.stringify(body), "utf8");
  return fetch(`${baseUrl}${path}`, {
    method,
    headers: {
      ...signedFoundryHeaders(path, method, rawBody),
      ...(body === undefined ? {} : { "Content-Type": "application/json" }),
    },
    body: body === undefined ? undefined : rawBody,
  });
}

function signedManagedHeaders(path, method, rawBody) {
  const timestamp = new Date().toISOString();
  const nonce = randomBytes(24).toString("base64url");
  const bodySha256 = sha256RawBody(rawBody);
  const payload = managedProvisionerSigningPayload({
    audience: managedProvisionerAudience,
    serviceId: managedProvisionerServiceId,
    keyId: managedProvisionerKeyId,
    method,
    path,
    timestamp,
    nonce,
    bodySha256,
  });
  const signature = sign(null, Buffer.from(payload, "utf8"), managedProvisionerPrivateKey).toString("base64url");
  return {
    [MANAGED_PROVISIONER_HEADERS.serviceId]: managedProvisionerServiceId,
    [MANAGED_PROVISIONER_HEADERS.keyId]: managedProvisionerKeyId,
    [MANAGED_PROVISIONER_HEADERS.audience]: managedProvisionerAudience,
    [MANAGED_PROVISIONER_HEADERS.timestamp]: timestamp,
    [MANAGED_PROVISIONER_HEADERS.nonce]: nonce,
    [MANAGED_PROVISIONER_HEADERS.bodySha256]: bodySha256,
    [MANAGED_PROVISIONER_HEADERS.signature]: signature,
  };
}

function signedFoundryHeaders(path, method, rawBody) {
  return signedHeaders({
    path,
    method,
    rawBody,
    audience: foundryProvisionerAudience,
    serviceId: foundryProvisionerServiceId,
    keyId: foundryProvisionerKeyId,
    privateKey: foundryProvisionerPrivateKey,
  });
}

function signedHeaders({ path, method, rawBody, audience, serviceId, keyId, privateKey }) {
  const timestamp = new Date().toISOString();
  const nonce = randomBytes(24).toString("base64url");
  const bodySha256 = sha256RawBody(rawBody);
  const payload = managedProvisionerSigningPayload({
    audience,
    serviceId,
    keyId,
    method,
    path,
    timestamp,
    nonce,
    bodySha256,
  });
  const signature = sign(null, Buffer.from(payload, "utf8"), privateKey).toString("base64url");
  return {
    [MANAGED_PROVISIONER_HEADERS.serviceId]: serviceId,
    [MANAGED_PROVISIONER_HEADERS.keyId]: keyId,
    [MANAGED_PROVISIONER_HEADERS.audience]: audience,
    [MANAGED_PROVISIONER_HEADERS.timestamp]: timestamp,
    [MANAGED_PROVISIONER_HEADERS.nonce]: nonce,
    [MANAGED_PROVISIONER_HEADERS.bodySha256]: bodySha256,
    [MANAGED_PROVISIONER_HEADERS.signature]: signature,
  };
}

function assertOneTimeCapabilityResponse(response) {
  assert.equal(response.headers.get("cache-control"), "no-store, max-age=0");
  assert.equal(response.headers.get("pragma"), "no-cache");
  assert.equal(response.headers.get("expires"), "0");
}

async function waitForHealth() {
  const deadline = Date.now() + 15_000;
  while (Date.now() < deadline) {
    try {
      const response = await fetch(`${baseUrl}/healthz`);
      if (response.ok) return;
    } catch {}
    await new Promise((resolve) => setTimeout(resolve, 100));
  }
  throw new Error("server_health_timeout");
}

async function readFirstPatch(response, controller) {
  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = "";
  const timeout = setTimeout(() => controller.abort(), 10_000);
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) throw new Error("stream_closed_before_patch");
      buffer += decoder.decode(value, { stream: true });
      for (const frame of buffer.split("\n\n")) {
        const data = frame.split("\n").find((line) => line.startsWith("data: "));
        if (frame.includes("event: nodedc.data-product.patch.v1") && data) {
          controller.abort();
          return JSON.parse(data.slice(6));
        }
      }
      const boundary = buffer.lastIndexOf("\n\n");
      if (boundary >= 0) buffer = buffer.slice(boundary + 2);
    }
  } finally {
    clearTimeout(timeout);
  }
}

async function readNamedEvent(response, eventName) {
  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = "";
  const deadline = Date.now() + 10_000;
  while (Date.now() < deadline) {
    const next = await Promise.race([
      reader.read(),
      new Promise((_, reject) => setTimeout(() => reject(new Error("stream_event_timeout")), 10_000)),
    ]);
    if (next.done) throw new Error(`stream_closed_before_${eventName}`);
    buffer += decoder.decode(next.value, { stream: true }).replace(/\r\n/g, "\n");
    let boundary;
    while ((boundary = buffer.indexOf("\n\n")) !== -1) {
      const frame = buffer.slice(0, boundary);
      buffer = buffer.slice(boundary + 2);
      if (!frame.includes(`event: ${eventName}`)) continue;
      const data = frame.split("\n").find((line) => line.startsWith("data: "));
      if (data) return JSON.parse(data.slice(6));
    }
  }
  throw new Error(`stream_event_timeout:${eventName}`);
}

async function waitForChildExit(process, timeoutMs) {
  if (process.exitCode !== null) return true;
  return Promise.race([
    new Promise((resolve) => process.once("exit", () => resolve(true))),
    new Promise((resolve) => setTimeout(() => resolve(false), timeoutMs)),
  ]);
}

async function freePort() {
  const server = net.createServer();
  await new Promise((resolve, reject) => server.listen(0, "127.0.0.1", resolve).once("error", reject));
  const { port } = server.address();
  await new Promise((resolve) => server.close(resolve));
  return port;
}
