/*
  Сервис публикации публичных криптографических ключей в формате JWK
*/
syntax = "proto3";

import "google/api/annotations.proto";
import "google/api/field_behavior.proto";
import "google/protobuf/descriptor.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";

package keyapis.jwks.v1;

option java_package = "ru.keyapis.jwks.v1";
option java_outer_classname = "KeyapisJwksV1Proto";
option java_multiple_files = false;
option java_string_check_utf8 = true;
option go_package = "/keyapis_jwks_v1";
option cc_enable_arenas = true;
option csharp_namespace = "Keyapis.Jwks.V1";
option objc_class_prefix = "KEYAPISJWKSV1";
option php_namespace = "Keyapis\\Jwks\\V1";
option ruby_package = "Keyapis::Jwks::V1";
option optimize_for = LITE_RUNTIME;

// Сервис JWKS
service KeyService {
  // Метод сохранения публичного ключа.
  // Используется сервисом KMS.
  // Сценарий использования метода: https://confluence.rt.ru/pages/viewpage.action?pageId=664695357.
  // Метод доступен для: service
  rpc PostKey(PostKeyRequest) returns (PostKeyResponse) {
    option (google.api.http) = {
      post: "/jwks/internal/api/v1/key",
      body: "*"
    };
  }

  // Метод удаления публичного ключа.
  // Используется сервисом KMS.
  // Метод доступен для: service
  rpc DeleteKey(DeleteKeyRequest) returns (DeleteKeyResponse) {
    option (google.api.http) = {
      delete: "/jwks/internal/api/v1/key/{id}"
    };
  }

  // Метод получения публичных ключей.
  // Возвращает три последних публичных ключа.
  // Используется партнёрами, с помощью публичного ключа проверяется подпись в JWT, выпущенных платформой Ключ.
  // Сценарий использования метода: https://confluence.rt.ru/pages/viewpage.action?pageId=664695865.
  // Не требует авторизации
  rpc GetKeyWellKnownJwksJson(GetKeyWellKnownJwksJsonRequest) returns (GetKeyWellKnownJwksJsonResponse) {
    option (google.api.http) = {
      get: "/jwks/api/v1/key/.well-known/jwks.json"
    };
  }
}

// Ключ.
// # Описание модели
message KeyInfo {
  // Идентификатор ключа, соответсвует kid.
  // # Тип: Guid
  string id = 1 [(google.api.field_behavior) = REQUIRED];
  // Публичный ключ
  message PublicKey {
    // Вид использования.
    // # Диапазон: 2..32
    string use = 1 [(google.api.field_behavior) = REQUIRED];
    // Тип ключа.
    // # Диапазон: 2..32
    string kty = 2 [(google.api.field_behavior) = REQUIRED];
    // Идентификатор.
    // # Тип: Guid
    string kid = 3 [(google.api.field_behavior) = REQUIRED];
    // Алгоритм шифрования.
    // # Диапазон: 2..32
    string alg = 4;
    // Параметр Modulus
    string n = 5 [(google.api.field_behavior) = REQUIRED];
    // Параметр Exponent
    string e = 6 [(google.api.field_behavior) = REQUIRED];
    // Цепочка сертификатов X.509.
    // # Диапазон: 0..100
    repeated string x5c = 7;
  }
  // Публичный ключ
  PublicKey public_key = 2 [(google.api.field_behavior) = REQUIRED];
  // Дата создания.
  // # Тип: DateTime
  google.protobuf.Timestamp created_at = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Ошибка сохранения.
  // Эти проверки выполняются при работе с базой данных и сторонними сервисами
  message SavingError {
    // Ключ с таким идентификатором уже существует.
    // Причины:
    // - В базе хранится запись с переданнм kid
    message KeyAlreadyExists {}
    // Причина ошибки
    oneof reason {
      // Ключ с таким идентификатором уже существует
      KeyAlreadyExists key_already_exists = 1;
    }
  }
}

// Запрос на сохранение публичного ключа
message PostKeyRequest {
  // Ключ
  KeyInfo.PublicKey data = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос на сохранение публичного ключа
message PostKeyResponse {
  // Ошибка
  message Error {
    // Причина
    oneof reason {
      // Ошибки валидации
      ValidationError validation = 1;
      // Ошибка сохранения
      KeyInfo.SavingError saving = 2;
    }
  }
  // Тип ответа
  oneof type {
    // Ошибка
    Error error = 1;
  }
}

// Запрос удаления публичного ключа
message DeleteKeyRequest {
  // Идентификатор ключа, соответсвует kid.
  // # Тип: Guid
  string id = 1 [(google.api.field_behavior) = REQUIRED];
}

// Ответ на запрос удаления публичного ключа
message DeleteKeyResponse {
  // Ошибка запроса удаления публичного ключа
  message Error {
    // Причина ошибки
    oneof reason {
      // Ошибка валидации
      ValidationError validation = 1;
    }
  }
  // Тип результата
  oneof type {
    // Ошибка
    Error error = 1;
  }
}

// Запрос на получение публичных ключей
message GetKeyWellKnownJwksJsonRequest {}

// Ответ на запрос на получение публичных ключей
message GetKeyWellKnownJwksJsonResponse {
  // Список ключей
  repeated KeyInfo.PublicKey data = 1 [json_name = "keys"];
}

// Ошибки валидации.
// Эти проверки выполняются до обращения в базу данных
message ValidationError {
  // Путь к полю в формате наименования прото
  string path = 1 [(google.api.field_behavior) = REQUIRED];
  // Валидационное сообщение
  string message = 2 [(google.api.field_behavior) = REQUIRED];
}
