requestSecretsFromNamespace method

Future<int> requestSecretsFromNamespace(
  1. String namespace, {
  2. List<String>? names,
  3. String? namePrefix,
  4. Set<String> excludeEnrollmentIds = const {},
})

Broadcasts a pull request for held secrets to every key package registered for namespace (minus this client). Holders that pass the answer policy reply by sharing the matching secrets; the caller typically then waitForSecrets. Filter the request by exact names and/or a namePrefix (e.g. __rk. for epoch keys). excludeEnrollmentIds drops revoked enrollments. Returns the number of key packages the request was sent to.

Implementation

Future<int> requestSecretsFromNamespace(
  String namespace, {
  List<String>? names,
  String? namePrefix,
  Set<String> excludeEnrollmentIds = const {},
}) async {
  final members = await directory.listForNamespace(namespace,
      excludeEnrollmentIds: excludeEnrollmentIds);
  final String selfId = enrollmentId;
  // ONE id for the whole fan-out: it is what lets a second holder see that a
  // first has already answered THIS request rather than other traffic at the
  // same address.
  final String requestId = Uuid().v4().replaceAll('-', '').substring(0, 16);
  int sent = 0;
  for (final member in members) {
    final to = member.keyPackage;
    if (to != null && to.kpid != null && !_isSelf(member, selfId)) {
      // Per member: sendEnvelope throws StateError when a member advertises
      // no mutually supported algorithm, and the design is N holders
      // precisely so that some can be unreachable.
      try {
        await sendEnvelope(
            to,
            namespace,
            {
              'kind': secretRequestKind,
              'requestId': requestId,
              if (names != null) 'want': names,
              if (namePrefix != null) 'namePrefix': namePrefix,
            },
            // The request answers nothing; its own id travels in the sealed
            // payload, where a holder can trust it.
            inReplyTo: EnvelopeAddressing.unsolicited);
        sent++;
      } catch (e) {
        if (e is StoppedException) rethrow;
        _throwIfStopped();
        // Warning, not finer: a request that never went out is
        // indistinguishable from one nobody answered.
        logger.warning('Could not request secrets from enrollment '
            '${member.enrollmentId} (kpid ${to.kpid}) in $namespace: $e. '
            'The remaining members are still being asked.');
      }
    }
  }
  return sent;
}