// Copyright 2026 Google LLC
//
// 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";

package google.cloud.apptopology.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/apptopology/v1/graph.proto";
import "google/cloud/apptopology/v1/query.proto";
import "google/cloud/apptopology/v1/schema.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Cloud.AppTopology.V1";
option go_package = "cloud.google.com/go/apptopology/apiv1/apptopologypb;apptopologypb";
option java_multiple_files = true;
option java_outer_classname = "ServiceProto";
option java_package = "com.google.cloud.apptopology.v1";
option php_namespace = "Google\\Cloud\\AppTopology\\V1";
option ruby_package = "Google::Cloud::AppTopology::V1";
option (google.api.resource_definition) = {
  type: "apptopology.googleapis.com/DiscoveredResourcesTopology"
  pattern: "projects/{project}/locations/{location}/discoveredResourcesTopology"
  plural: "discoveredResourcesTopologies"
  singular: "discoveredResourcesTopology"
};

// Service describing handlers for resources
service AppTopology {
  option (google.api.default_host) = "apptopology.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/apptopology.read-only,"
      "https://www.googleapis.com/auth/apptopology.read-write,"
      "https://www.googleapis.com/auth/cloud-platform";

  // Generate the topology for all resources in the given project. If the
  // project represents an
  // [app
  // boundary](https://cloud.google.com/app-hub/docs/reference/rest/v1/Boundary),
  // the topology is generated for all resources in the boundary.
  rpc GenerateDiscoveredResourcesTopology(
      GenerateDiscoveredResourcesTopologyRequest)
      returns (GenerateDiscoveredResourcesTopologyResponse) {
    option (google.api.http) = {
      post: "/v1/{name=projects/*/locations/*/discoveredResourcesTopology}:generate"
      body: "*"
    };
    option (google.api.method_signature) = "name,topology_domains";
  }

  // Retrieves the schema for the specified topology domain. The schema
  // defines the NodeTypes and EdgeTypes that are supported in
  // GenerateDiscoveredResourcesTopology requests and responses for a given
  // domain.
  rpc GetSchema(GetSchemaRequest) returns (Schema) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/domains/*/schema}"
    };
    option (google.api.method_signature) = "name";
  }

  // Explores the topology schema starting from given node types or label names
  // up to a specified hop depth.
  rpc ExploreSchema(ExploreSchemaRequest) returns (ExploreSchemaResponse) {
    option (google.api.http) = {
      post: "/v1/{name=projects/*/locations/*/domains/*/schema}:explore"
      body: "*"
    };
    option (google.api.method_signature) = "name";
  }

  // Retrieves the specified topology domain.
  rpc GetDomain(GetDomainRequest) returns (Domain) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/domains/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists the topology domains available in a specific location.
  // Only `global` location is supported.
  rpc ListDomains(ListDomainsRequest) returns (ListDomainsResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*/locations/*}/domains"
    };
    option (google.api.method_signature) = "parent";
  }
}

// Represents the metadata of the long-running operation.
message OperationMetadata {
  // Output only. The time the operation was created.
  google.protobuf.Timestamp create_time = 1
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time the operation finished running.
  google.protobuf.Timestamp end_time = 2
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Server-defined resource path for the target of the operation.
  string target = 3 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Name of the verb executed by the operation.
  string verb = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Human-readable status of the operation, if any.
  string status_message = 5 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Identifies whether the user has requested cancellation
  // of the operation. Operations that have been cancelled successfully
  // have
  // [google.longrunning.Operation.error][google.longrunning.Operation.error]
  // value with a [google.rpc.Status.code][google.rpc.Status.code] of `1`,
  // corresponding to `Code.CANCELLED`.
  bool requested_cancellation = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. API version used to start the operation.
  string api_version = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Request for GenerateDiscoveredResourcesTopology.
message GenerateDiscoveredResourcesTopologyRequest {
  // Query the topology by building a graph pattern filter or pre-defined
  // topology view.
  oneof query {
    // Filters for the topology nodes and edges; Detail format see GraphPattern
    // proto. A separate 'LookupSchema' method will be added that will return
    // the necessary information to be able to construct these filters.
    GraphPattern filter = 3;
  }

  // Required. The project to query discoverable resources on.
  // Expected format:
  // `projects/{project}/locations/{location}/discoveredResourcesTopology`.
  // Only `global` location is supported.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "apptopology.googleapis.com/DiscoveredResourcesTopology"
    }
  ];

  // Required. The full resource name of the domain of the app topology.
  // Format: `projects/{project}/locations/{location}/domains/{domain}`
  // Caller must have apptopology.domains.get permission on each of the domains.
  repeated string topology_domains = 2 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "apptopology.googleapis.com/Domain"
    }
  ];
}

// Response for GenerateDiscoveredResourcesTopology.
message GenerateDiscoveredResourcesTopologyResponse {
  // The generated topology graph.
  Graph graph = 1;
}

// Request for GetSchema.
message GetSchemaRequest {
  // Required. The name of the singleton domain schema resource.
  // Format: `projects/{project}/locations/{location}/domains/{domain}/schema`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "apptopology.googleapis.com/Schema"
    }
  ];
}

// Request for ExploreSchema.
message ExploreSchemaRequest {
  // Required. The name of the singleton domain schema resource.
  // Format: `projects/{project}/locations/{location}/domains/{domain}/schema`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "apptopology.googleapis.com/Schema"
    }
  ];

  // Optional. Starting label names to begin traversal.
  // Substring, case-insensitive matches are performed against allowed label
  // names in the schema. A maximum of 10 `start_labels` can be specified;
  // providing more will result in an `INVALID_ARGUMENT` error.
  // If `start_labels` is unset or empty, all authorized node types will be used
  // as the starting set.
  repeated string start_labels = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The maximum depth of BFS traversal hops to perform from the
  // starting node types or label names. Defaults to 0 if unspecified.
  int32 depth = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The maximum number of schema elements to return in a single page.
  //
  // - The service might return fewer elements than this value if adding another
  //   edge and its required endpoint nodes exceeds `page_size`.
  // - If omitted or set to 0, default (100) will be used.
  // - Minimum page_size is 3 to ensure at least one edge and its endpoint
  //   nodes fit on a page; values below 3 (e.g. 1 or 2) are changed to 3.
  // - Maximum value is 500.
  int32 page_size = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A page token received from a previous `ExploreSchema` call.
  // Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters (except page_size) provided to
  // `ExploreSchema` must match the call that provided the page token.
  string page_token = 6 [(google.api.field_behavior) = OPTIONAL];
}

// Response for ExploreSchema.
message ExploreSchemaResponse {
  // A list of `NodeType`s defined within this schema.
  // Refer to the documentation of `NodeType` for more details.
  repeated NodeType node_types = 1;

  // A list of `EdgeType`s defined within this schema.
  // Refer to the documentation of `EdgeType` for more details.
  repeated EdgeType edge_types = 2;

  // A list of supported labels and corresponding properties.
  repeated LabelProperties label_properties = 3;

  // Edge rules. These will indicate which node types can be connected and
  // through what edge type. This is a list of (source_node_type, edge_type,
  // destination_node_type) tuples.
  repeated EdgeRule edge_rules = 4;

  // A token to retrieve the next page of results, or empty if there are no
  // more results in the traversal set.
  string next_page_token = 5;
}

// Request for GetDomain.
message GetDomainRequest {
  // Required. The name of the domain to retrieve.
  // Format: `projects/{project}/locations/{location}/domains/{domain}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "apptopology.googleapis.com/Domain"
    }
  ];
}

// Request for ListDomains.
message ListDomainsRequest {
  // Required. The parent location to list domains for.
  // Format: `projects/{project}/locations/{location}`
  // Only `global` location is supported.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "apptopology.googleapis.com/Domain"
    }
  ];

  // Optional. The maximum number of domains to return. The service may return
  // fewer than this value. If unspecified, at most 50 domains will be returned.
  // The maximum value is 1000; values above 1000 will be coerced to 1000.
  int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A page token, received from a previous `ListDomains` call.
  // Provide this to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided to `ListDomains` must match
  // the call that provided the page token.
  string page_token = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Response for ListDomains.
message ListDomainsResponse {
  // The domains in the specified location.
  repeated Domain domains = 1;

  // A token that can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}
