// PureLife Device Provisioning Protocol, version 1.0 (Draft).
//
// Endpoint `pld-pair`: obtains a pairing token from the Server. The
// Provisioner redeems the token against the PureLife Cloud API to link the
// Device to a Customer. The request to the Server is asynchronous: the
// Provisioner starts it and polls the result.
// See the Device Provisioning Protocol (pld-provisioning.html), section 11.

syntax = "proto3";

package pld;

import "pld_constants.proto";

// Type of the message carried in `PairPayload`.
enum PairMsgType {
  // Not set. A payload with this type is invalid.
  PAIR_MSG_TYPE_UNSPECIFIED = 0;

  // Provisioner to Device: `StartPairingCommand`.
  PAIR_MSG_TYPE_START_PAIRING_COMMAND = 1;

  // Device to Provisioner: `StartPairingResponse`.
  PAIR_MSG_TYPE_START_PAIRING_RESPONSE = 2;

  // Provisioner to Device: `GetPairingStatusCommand`.
  PAIR_MSG_TYPE_GET_PAIRING_STATUS_COMMAND = 3;

  // Device to Provisioner: `GetPairingStatusResponse`.
  PAIR_MSG_TYPE_GET_PAIRING_STATUS_RESPONSE = 4;
}

// State of the pairing token request.
enum PairState {
  // Not set. A response with this state is invalid.
  PAIR_STATE_UNSPECIFIED = 0;

  // No request has been started in this session.
  PAIR_STATE_IDLE = 1;

  // The request to the Server is running. Poll again.
  PAIR_STATE_RUNNING = 2;

  // The token was obtained. `token` and `expires_at` are set.
  PAIR_STATE_DONE = 3;

  // The request failed. `error` says why.
  PAIR_STATE_FAILED = 4;
}

// Reason for a failed pairing token request.
enum PairError {
  // No error. The default unless `state` is `PAIR_STATE_FAILED`.
  PAIR_ERROR_NONE = 0;

  // The Server could not be reached. Run the Server check for details.
  PAIR_ERROR_SERVER_UNREACHABLE = 1;

  // The Server answered with an error status.
  // `GetPairingStatusResponse.http_status` holds it: 401 after one failed
  // re-authentication, 403 when the Device is blocked, 429 or 503 when
  // the Server asks to retry later.
  PAIR_ERROR_SERVER_REJECTED = 2;

  // Value 3 was `PAIR_ERROR_DEVICE_UNKNOWN` in an earlier draft. The
  // Device is always known to the Server once it is authenticated.
  reserved 3;

  // No answer within 30 seconds.
  PAIR_ERROR_TIMEOUT = 4;

  // Any other error. `detail` should explain.
  PAIR_ERROR_INTERNAL = 5;
}

// Requests a pairing token from the Server.
//
// Requires a Commit (`STATUS_INVALID_STATE` otherwise). A running request
// answers `STATUS_BUSY`. A new request invalidates the previous token. Has
// no fields.
message StartPairingCommand {}

// Result of `StartPairingCommand`.
message StartPairingResponse {
  // Required. Result of the command.
  Status status = 1;

  // Optional. Human readable detail for logs and support, English, at most
  // 64 bytes. MUST be empty when `status` is `STATUS_OK`.
  string detail = 2;
}

// Requests the state and result of the pairing token request. Has no
// fields.
message GetPairingStatusCommand {}

// State and result of the pairing token request.
message GetPairingStatusResponse {
  // Required. Result of the command.
  Status status = 1;

  // Optional. Human readable detail for logs and support, English, at most
  // 64 bytes. MUST be empty when `status` is `STATUS_OK`.
  string detail = 2;

  // Required. State of the request.
  PairState state = 3;

  // Reason for the failure. `PAIR_ERROR_NONE` unless `state` is
  // `PAIR_STATE_FAILED`.
  PairError error = 4;

  // HTTP status code. Set only when `error` is
  // `PAIR_ERROR_SERVER_REJECTED`; 0 otherwise.
  uint32 http_status = 5;

  // The pairing token, opaque, 43 characters base64url. Set only when
  // `state` is `PAIR_STATE_DONE`; empty otherwise. Must not be logged.
  string token = 6;

  // Expiry time of the token, Unix milliseconds UTC, set by the Server. Set
  // only when `state` is `PAIR_STATE_DONE`; 0 otherwise.
  int64 expires_at = 7;
}

// Payload of the `pld-pair` endpoint.
message PairPayload {
  // Required. Identifies which member of `payload` is set.
  PairMsgType msg = 1;

  // The command or response. Exactly one member is set.
  oneof payload {
    // Set when `msg` is `PAIR_MSG_TYPE_START_PAIRING_COMMAND`.
    StartPairingCommand start_pairing_command = 10;

    // Set when `msg` is `PAIR_MSG_TYPE_START_PAIRING_RESPONSE`.
    StartPairingResponse start_pairing_response = 11;

    // Set when `msg` is `PAIR_MSG_TYPE_GET_PAIRING_STATUS_COMMAND`.
    GetPairingStatusCommand get_pairing_status_command = 12;

    // Set when `msg` is `PAIR_MSG_TYPE_GET_PAIRING_STATUS_RESPONSE`.
    GetPairingStatusResponse get_pairing_status_response = 13;
  }
}
