OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / test / unit / public-hive-gateway-release-manifest.test.js

184 lines · javascript ref:
import test from 'brittle'
import { encodeHiveAppKey } from '../../packages/core/gateway/hive-host.js'
import {
  assertOperatorContractMatchesCohort,
  cohortEntryForRelay,
  cohortEntriesForChannel,
  normalizePublicHiveGatewayOperatorContract,
  normalizePublicHiveGatewayReleaseManifest,
  operatorContractPathForRelay,
  sha256PublicHiveGatewayOperatorContract
} from '../../scripts/lib/public-hive-gateway-release-manifest.mjs'
import { PUBLIC_HIVE_GATEWAY_FINITE_POLICY } from '../../scripts/lib/public-hive-gateway-policy.mjs'

const APP_KEY = 'aa'.repeat(32)
const SUFFIX = 'hive-canary.operator.example'
const LABEL = encodeHiveAppKey(Buffer.from(APP_KEY, 'hex'))
const FINGERPRINT = Array(32).fill('AA').join(':')

test('public gateway release manifest binds a signed release to an exact cohort identity', (t) => {
  const manifest = normalizePublicHiveGatewayReleaseManifest(fixture(), { releaseTarget: 'v1.2.3' })

  t.is(manifest.releaseTarget, 'v1.2.3')
  t.is(manifest.admissionProfile, 'blind-substrate-public-v1')
  t.is(manifest.observationWindowMs, 24 * 60 * 60 * 1000)
  t.is(manifest.cohort.length, 1)
  t.alike(cohortEntryForRelay(manifest, 'canary-1'), {
    relay: 'canary-1',
    channel: 'canary',
    suffix: SUFFIX,
    origin: `https://${LABEL}.${SUFFIX}`,
    connectAddress: '127.0.0.1',
    appKey: APP_KEY,
    path: '/index.html',
    contentSha256: 'bb'.repeat(32),
    driveVersion: '7',
    peerFingerprint256: FINGERPRINT,
    nginxConfigSha256: 'cc'.repeat(32)
  })
  t.alike(cohortEntriesForChannel(manifest, 'canary').map(entry => entry.relay), ['canary-1'])
  t.alike(cohortEntriesForChannel(manifest, 'stable'), [])
})

test('public gateway release manifest fails closed on transitional, stale, and ambiguous policy', (t) => {
  const disabled = fixture()
  disabled.enabled = false
  t.exception(() => normalizePublicHiveGatewayReleaseManifest(disabled), /explicitly enabled/)

  const transitional = fixture()
  transitional.admissionProfile = 'transitional-operator-allowlist-v1'
  t.exception(() => normalizePublicHiveGatewayReleaseManifest(transitional), /frozen admissionProfile/)

  const shortWindow = fixture()
  shortWindow.observationWindowMs = 60 * 60 * 1000
  t.exception(() => normalizePublicHiveGatewayReleaseManifest(shortWindow), /between 24 hours and 7 days/)

  const mismatchedOrigin = fixture()
  mismatchedOrigin.cohort[0].origin = 'https://example.com/'
  t.exception(() => normalizePublicHiveGatewayReleaseManifest(mismatchedOrigin), /exact appKey and suffix/)

  const duplicated = fixture()
  duplicated.cohort.push({ ...duplicated.cohort[0] })
  t.exception(() => normalizePublicHiveGatewayReleaseManifest(duplicated), /repeats relay/)

  const unknown = fixture()
  unknown.cohort[0].unexpected = true
  t.exception(() => normalizePublicHiveGatewayReleaseManifest(unknown), /unsupported fields/)

  const unsafeVersion = fixture()
  unsafeVersion.cohort[0].driveVersion = String(Number.MAX_SAFE_INTEGER + 1)
  t.exception(() => normalizePublicHiveGatewayReleaseManifest(unsafeVersion), /safe integer string/)

  t.exception(() => normalizePublicHiveGatewayReleaseManifest(fixture(), { releaseTarget: 'v1.2.4' }), /must target v1.2.4/)
  t.exception(() => cohortEntryForRelay(normalizePublicHiveGatewayReleaseManifest(fixture()), 'other'), /does not uniquely approve/)
})

test('public gateway release manifest binds public-t1 cohort to one canonical operator contract digest', (t) => {
  const contract = operatorFixture()
  const digest = sha256PublicHiveGatewayOperatorContract(contract)
  const source = fixture()
  source.cohort[0].deploymentProfile = 'public-t1-gateway'
  source.cohort[0].operatorContractSha256 = digest
  const manifest = normalizePublicHiveGatewayReleaseManifest(source, { requirePublicT1: true })
  const entry = cohortEntryForRelay(manifest, 'canary-1')
  const matched = assertOperatorContractMatchesCohort(contract, manifest, entry)

  t.is(entry.deploymentProfile, 'public-t1-gateway')
  t.is(entry.operatorContractSha256, digest)
  t.is(matched.digest, digest)
  t.is(matched.contract.certificateSpkiSha256, 'dd'.repeat(32))
  t.is(operatorContractPathForRelay('canary-1'), 'fleet/public-hive-gateway-operators/canary-1.json')

  const reordered = operatorFixture()
  reordered.expectedAddresses.reverse()
  t.is(sha256PublicHiveGatewayOperatorContract(reordered), digest, 'canonical digest ignores source key/address order')

  const missingDigest = fixture()
  missingDigest.cohort[0].deploymentProfile = 'public-t1-gateway'
  t.exception(() => normalizePublicHiveGatewayReleaseManifest(missingDigest), /operatorContractSha256 is required/)

  const profileTypo = fixture()
  profileTypo.cohort[0].deploymentProfile = 'public-tl-gateway'
  profileTypo.cohort[0].operatorContractSha256 = digest
  t.exception(() => normalizePublicHiveGatewayReleaseManifest(profileTypo), /must be exactly public-t1-gateway/)

  const drifted = operatorFixture()
  drifted.certificateSpkiSha256 = 'ee'.repeat(32)
  t.exception(() => assertOperatorContractMatchesCohort(drifted, manifest, entry), /digest does not match/)

  const normalized = normalizePublicHiveGatewayOperatorContract(contract, { releaseTarget: 'v1.2.3' })
  t.is(normalized.release.expectedPath, '/index.html')
  t.exception(() => normalizePublicHiveGatewayOperatorContract({ ...contract, unknown: true }), /unsupported fields/)

  const oldSchema = operatorFixture()
  oldSchema.schema = 'hiverelay-public-gateway-operator-contract-v1'
  t.exception(() => normalizePublicHiveGatewayOperatorContract(oldSchema), /schema/)
  const missingPhysicalRequirement = operatorFixture()
  delete missingPhysicalRequirement.physicalEnforcementRequired
  t.exception(() => normalizePublicHiveGatewayOperatorContract(missingPhysicalRequirement), /physicalEnforcementRequired/)
  t.exception(() => normalizePublicHiveGatewayOperatorContract({
    ...operatorFixture(),
    physicalEnforcementRequired: false
  }), /physicalEnforcementRequired/)
})

test('public gateway release manifest keeps historical parsing but rejects legacy cohorts for new publication', (t) => {
  const historical = normalizePublicHiveGatewayReleaseManifest(fixture())
  t.is(historical.cohort[0].deploymentProfile, undefined, 'historical legacy manifests remain readable')
  t.exception(() => normalizePublicHiveGatewayReleaseManifest(fixture(), { requirePublicT1: true }),
    /must use public-t1-gateway with a canonical operator contract digest/)
})

function fixture () {
  return {
    schema: 'hiverelay-public-gateway-release-v1',
    enabled: true,
    releaseTarget: 'v1.2.3',
    admissionProfile: 'blind-substrate-public-v1',
    observationWindowMs: 24 * 60 * 60 * 1000,
    maxProbeGapMs: 20 * 60 * 1000,
    cohort: [{
      relay: 'canary-1',
      channel: 'canary',
      suffix: SUFFIX,
      origin: `https://${LABEL}.${SUFFIX}/`,
      connectAddress: '127.0.0.1',
      appKey: APP_KEY,
      path: '/index.html',
      contentSha256: 'bb'.repeat(32),
      driveVersion: '7',
      peerFingerprint256: FINGERPRINT,
      nginxConfigSha256: 'cc'.repeat(32)
    }]
  }
}

function operatorFixture () {
  return {
    schema: 'hiverelay-public-gateway-operator-contract-v2',
    deploymentProfile: 'public-t1-gateway',
    relay: 'canary-1',
    channel: 'canary',
    operatorId: 'operator-a',
    registrableDomain: 'operator.example',
    apiHostname: 'relay-api.operator.example',
    suffix: SUFFIX,
    appKey: APP_KEY,
    addressFamilyPolicy: 'dual-stack',
    expectedAddresses: ['2606:4700:4700::1111', '8.8.8.8'],
    expectedConnectAddress: '127.0.0.1',
    certificateFingerprint256: FINGERPRINT,
    certificateSpkiSha256: 'dd'.repeat(32),
    publicSuffixReady: false,
    physicalEnforcementRequired: true,
    finiteProductionPolicy: { ...PUBLIC_HIVE_GATEWAY_FINITE_POLICY },
    release: {
      target: 'v1.2.3',
      expectedPath: '/index.html',
      expectedContentSha256: 'bb'.repeat(32),
      expectedDriveVersion: '7',
      expectedNginxSha256: 'cc'.repeat(32)
    }
  }
}