| … | … | @@ -352,7 +352,6 @@ export function buildCapabilityDoc (opts = {}) { |
| 352 | 352 | version: opts.version || null, |
| 353 | 353 | runtime, |
| 354 | 354 | region, |
| 355 | operator, | |
| 356 | 355 | contact: opts.contact || config.contact || null, |
| 357 | 356 | terms_of_service: opts.termsOfService || config.termsOfService || null, |
| 358 | 357 | supported_transports: transports, |
| … | … | @@ -393,6 +392,13 @@ export function buildCapabilityDoc (opts = {}) { |
| 393 | 392 | // advertisements (hiverelay.onion/1). Omitted unless verified ready |
| 394 | 393 | // (added below only when non-empty, preserving the signable shape). |
| 395 | 394 | ...(privacyTransports.length > 0 ? { privacyTransports } : {}), |
| 395 | // operator — present only when declared, for the same reason: the canonical | |
| 396 | // signer covers every key, so emitting `operator: null` everywhere would | |
| 397 | // change the signed bytes of every relay in the fleet, including the ones | |
| 398 | // that have nothing to say. Conditional inclusion keeps the default | |
| 399 | // signable shape byte-identical (the checked-in capability-doc conformance | |
| 400 | // vector pins it) and changes the doc only where it carries information. | |
| 401 | ...(operator ? { operator } : {}), | |
| 396 | 402 | // indexRoom — z32 link to this relay's schema-sheets index room, if a |
| 397 | 403 | // sidecar has published one. Additive: clients that don't understand it |
| 398 | 404 | // ignore it and fall back to catalogBeeKey / /catalog.json. schemaVersion |
| … | … | @@ -81,8 +81,12 @@ test('publishes operator identity so quorum diversity can be counted honestly', |
| 81 | 81 | // own operator — so five boxes in one datacenter under one owner satisfied a |
| 82 | 82 | // minOperators floor of five. The CLI accepted --operator all along; it was |
| 83 | 83 | // simply never published, so no client could see the concentration. |
| 84 | // Absent, not null: the canonical signer covers every key present, so | |
| 85 | // emitting `operator: null` everywhere would change the signed bytes of every | |
| 86 | // relay — including those with nothing to declare — and break the checked-in | |
| 87 | // capability-doc conformance vector that pins the default signable shape. | |
| 84 | 88 | const unset = buildCapabilityDoc({ relay: { config: {} } }) |
| 85 | t.is(unset.operator, null, 'absent when the operator has not declared one') | |
| 89 | t.absent('operator' in unset, 'key is omitted entirely when undeclared') | |
| 86 | 90 | |
| 87 | 91 | const declared = buildCapabilityDoc({ |
| 88 | 92 | relay: { config: { operator: 'hive-foundation-utah', regions: ['NA'] } } |
| … | … | @@ -90,7 +94,7 @@ test('publishes operator identity so quorum diversity can be counted honestly', |
| 90 | 94 | t.is(declared.operator, 'hive-foundation-utah') |
| 91 | 95 | t.is(declared.region, 'NA') |
| 92 | 96 | |
| 93 | t.is(buildCapabilityDoc({ relay: { config: { operator: ' ' } } }).operator, null, | |
| 97 | t.absent('operator' in buildCapabilityDoc({ relay: { config: { operator: ' ' } } }), | |
| 94 | 98 | 'whitespace is not an operator identity') |
| 95 | 99 | }) |
| 96 | 100 |