// Copyright 2018 clair authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

import "google/protobuf/timestamp.proto";

import "google/api/annotations.proto";

package coreos.clair;

option go_package = "clairpb";
option java_package = "com.coreos.clair.pb";

service AncestryService {
  // The RPC used to read the results of scanning for a particular ancestry.
  rpc GetAncestry(GetAncestryRequest) returns (GetAncestryResponse) {
    option (google.api.http) = { get: "/ancestry/{ancestry_name}" };
  }
  // The RPC used to create a new scan of an ancestry.
  rpc PostAncestry(PostAncestryRequest) returns (PostAncestryResponse) {
    option (google.api.http) = {
      post: "/ancestry"
      body: "*"
    };
  }
}

service StatusService {
  // The RPC used to show the internal state of current Clair instance.
  rpc GetStatus(GetStatusRequest) returns (GetStatusResponse) {
    option (google.api.http) = { get: "/status" };
  }
}

service NotificationService {
  // The RPC used to get a particularly Notification.
  rpc GetNotification(GetNotificationRequest) returns (GetNotificationResponse) {
    option (google.api.http) = { get: "/notifications/{name}" };
  }
  // The RPC used to mark a Notification as read after it has been processed.
  rpc MarkNotificationAsRead(MarkNotificationAsReadRequest) returns (MarkNotificationAsReadResponse) {
    option (google.api.http) = { delete: "/notifications/{name}" };
  }
}

message Vulnerability {
  // The name of the vulnerability.
  string name = 1;
  // The name of the namespace in which the vulnerability was detected.
  string namespace_name = 2;
  // A description of the vulnerability according to the source for the namespace.
  string description = 3;
  // A link to the vulnerability according to the source for the namespace.
  string link = 4;
  // How dangerous the vulnerability is.
  string severity = 5;
  // Namespace agnostic metadata about the vulnerability.
  string metadata = 6;
  // The feature that fixes this vulnerability.
  // This field only exists when a vulnerability is a part of a Feature.
  string fixed_by = 7;
  // The Features that are affected by the vulnerability.
  // This field only exists when a vulnerability is a part of a Notification.
  repeated Feature affected_versions = 8;
}

message Detector {
  enum DType {
    DETECTOR_D_TYPE_INVALID = 0;
    DETECTOR_D_TYPE_NAMESPACE = 1;
    DETECTOR_D_TYPE_FEATURE = 2;
  }
  // The name of the detector.
  string name = 1;
  // The version of the detector.
  string version = 2;
  // The type of the detector.
  DType dtype = 3;
}

message Namespace {
  // The name of the namespace.
  string name = 1;
  // The detector used to detect the namespace. This only exists when present in
  // an Ancestry Feature.
  Detector detector = 2;
}

message Feature {
  // The name of the feature.
  string name = 1;
  // The namespace in which the feature is detected.
  Namespace namespace = 2;
  // The specific version of this feature.
  string version = 3;
  // The format used to parse version numbers for the feature.
  string version_format = 4;
  // The detector used to detect this feature. This only exists when present in
  // an Ancestry.
  Detector detector = 5;
  // The list of vulnerabilities that affect the feature.
  repeated Vulnerability vulnerabilities = 6;
  // The feature type indicates if the feature represents a source package or
  // binary package.
  string feature_type = 7;
}

message Layer {
  // The sha256 tarsum for the layer.
  string hash = 1;
}

message ClairStatus {
  // The implemented detectors in this Clair instance
  repeated Detector detectors = 1;
  // The time at which the updater last ran.
  google.protobuf.Timestamp last_update_time = 2;
}

message GetAncestryRequest {
  // The name of the desired ancestry.
  string ancestry_name = 1;
}

message GetAncestryResponse {
  message AncestryLayer {
    // The layer's information.
    Layer layer = 1;
    // The features detected in this layer.
    repeated Feature detected_features = 2;
  }
  message Ancestry {
    // The name of the desired ancestry.
    string name = 1;
    // The detectors used to scan this Ancestry. It may not be the current set
    // of detectors in clair status.
    repeated Detector detectors = 2;
    // The list of layers along with detected features in each.
    repeated AncestryLayer layers = 3;
  }
  // The ancestry requested.
  Ancestry ancestry = 1;
  // The status of Clair at the time of the request.
  ClairStatus status = 2;
}

message PostAncestryRequest {
  message PostLayer {
    // The hash of the layer.
    string hash = 1;
    // The location of the layer (URL or file path).
    string path = 2;
    // Any HTTP Headers that need to be used if requesting a layer over HTTP(S).
    map<string, string> headers = 3;
  }
  // The name of the ancestry being scanned.
  // If scanning OCI images, this should be the hash of the manifest.
  string ancestry_name = 1;
  // The format of the image being uploaded.
  string format = 2;
  // The layers to be scanned for this Ancestry, ordered in the way that i th
  // layer is the parent of i + 1 th layer.
  repeated PostLayer layers = 3;
}

message PostAncestryResponse {
  // The status of Clair at the time of the request.
  ClairStatus status = 1;
}

message GetNotificationRequest {
  // The current page of previous vulnerabilities for the ancestry.
  // This will be empty when it is the first page.
  string old_vulnerability_page = 1;
  // The current page of vulnerabilities for the ancestry.
  // This will be empty when it is the first page.
  string new_vulnerability_page = 2;
  // The requested maximum number of results per page.
  int32 limit = 3;
  // The name of the notification being requested.
  string name = 4;
}

message GetNotificationResponse {
  message Notification {
    // The name of the requested notification.
    string name = 1;
    // The time at which the notification was created.
    string created = 2;
    // The time at which the notification was last sent out.
    string notified = 3;
    // The time at which a notification has been deleted.
    string deleted = 4;
    // The previous vulnerability and a paginated view of the ancestries it affects.
    PagedVulnerableAncestries old = 5;
    // The newly updated vulnerability and a paginated view of the ancestries it affects.
    PagedVulnerableAncestries new = 6;
  }
  // The notification as requested.
  Notification notification = 1;
}

message PagedVulnerableAncestries {
  message IndexedAncestryName {
    // The index is an ever increasing number associated with the particular ancestry.
    // This is useful if you're processing notifications, and need to keep track of the progress of paginating the results.
    int32 index = 1;
    // The name of the ancestry.
    string name = 2;
  }
  // The identifier for the current page.
  string current_page = 1;
  // The token used to request the next page.
  // This will be empty when there are no more pages.
  string next_page = 2;
  // The requested maximum number of results per page.
  int32 limit = 3;
  // The vulnerability that affects a given set of ancestries.
  Vulnerability vulnerability = 4;
  // The ancestries affected by a vulnerability.
  repeated IndexedAncestryName ancestries = 5;
}

message MarkNotificationAsReadRequest {
  // The name of the Notification that has been processed.
  string name = 1;
}

message MarkNotificationAsReadResponse {}

message GetStatusRequest {}

message GetStatusResponse {
  // The status of the current Clair instance.
  ClairStatus status = 1;
}
