// 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/field_behavior.proto";
import "google/api/resource.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 = "SchemaProto";
option java_package = "com.google.cloud.apptopology.v1";
option php_namespace = "Google\\Cloud\\AppTopology\\V1";
option ruby_package = "Google::Cloud::AppTopology::V1";

// Domain is a pre-defined topology query domain. Each topology domain
// contains a set of nodes and edges.
message Domain {
  option (google.api.resource) = {
    type: "apptopology.googleapis.com/Domain"
    pattern: "projects/{project}/locations/{location}/domains/{domain}"
    plural: "domains"
    singular: "domain"
  };

  // Identifier. The pre-defined topology domain.
  // Currently only SRE, DEVOPS, and SECURITY are available.
  // Format: `projects/{project}/locations/{location}/domains/{domain}`
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];
}

// Schema is a collection of supported node & edge labels and properties for an
// overlay.
message Schema {
  option (google.api.resource) = {
    type: "apptopology.googleapis.com/Schema"
    pattern: "projects/{project}/locations/{location}/domains/{domain}/schema"
    plural: "schemas"
    singular: "schema"
  };

  // Identifier. The resource name of the schema.
  // Format:
  // `projects/{project}/locations/{location}/domains/{domain}/schema`
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

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

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

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

  // 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 = 5;
}

// NodeType defines the schema of a node type in the graph.
message NodeType {
  // REQUIRED
  // Name of the node type.
  // This name is used to access the node type while defining the schema.
  string type = 1;

  // Labels attached to the node. Composable, namespaced building blocks that
  // define core attributes through associated properties. Multiple labels
  // aggregate to fully specify the functional traits and property schema of the
  // node type.
  repeated string labels = 2;

  // A human-readable description of the `NodeType`.
  string description = 3;

  // A node of this node type can have 0 or more of these labels. These node
  // objects of this node type will have these labels alongside the
  // required labels.
  repeated string optional_labels = 4;
}

// EdgeType defines the schema of an edge type in the graph.
message EdgeType {
  // REQUIRED
  // Name of the edge type.
  // This name is used to access the edge type while defining the schema.
  string type = 1;

  // Labels attached to the edge. Composable, namespaced building blocks that
  // define core attributes through associated properties. Multiple labels
  // aggregate to fully specify the functional traits and property schema of the
  // edge type.
  repeated string labels = 2;

  // A human-readable description of the `EdgeType`.
  string description = 3;

  // An edge of this edge type can have 0 or more of these labels. These edge
  // objects of this edge type will have these labels alongside the
  // required labels.
  repeated string optional_labels = 4;
}

// NodeGroup represents a dynamic collection of nodes that satisfy specific
// criteria. A node is considered part of this group if it matches the defined
// constraints.
message NodeGroup {
  // Optional. A node must have at least one of these labels to be included in
  // the group. If empty or unset, this constraint is not applied.
  repeated string any_labels = 1 [(google.api.field_behavior) = OPTIONAL];
}

// EdgeRule defines the connection rules for nodes in the graph.
message EdgeRule {
  // Specifies the source criteria for this edge rule.
  // An edge rule must define its source either statically via a specific
  // node type, or dynamically via a group of nodes that match given
  // constraints.
  //
  // This takes precedence over the `source_node_type` field.
  oneof source_node {
    // Optional. The specific node type name that acts as the source for this
    // edge.
    string src_node_type = 4 [(google.api.field_behavior) = OPTIONAL];

    // Optional. A dynamic group of nodes, defined by label constraints, that
    // can act as the source for this edge.
    NodeGroup src_node_group = 5 [(google.api.field_behavior) = OPTIONAL];
  }

  // Specifies the destination criteria for this edge rule.
  // An edge rule must define its destination either statically via a specific
  // node type, or dynamically via a group of nodes that match given
  // constraints.
  //
  // This takes precedence over the `destination_node_type` field.
  oneof destination_node {
    // Optional. The specific node type name that acts as the destination for
    // this edge.
    string dest_node_type = 6 [(google.api.field_behavior) = OPTIONAL];

    // Optional. A dynamic group of nodes, defined by label constraints, that
    // can act as the destination for this edge.
    NodeGroup dest_node_group = 7 [(google.api.field_behavior) = OPTIONAL];
  }

  // Optional. Name of the connected edge type.
  string edge_type = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Identifier for the label and corresponding properties.
message LabelProperties {
  // Full qualified name of the label.
  string label = 1;

  // List of properties associated with the label.
  repeated Property properties = 2;

  // A human-readable description of the label.
  string description = 3;
}

// Property defines the schema of a property in the graph.
message Property {
  // REQUIRED
  // Value type of the property.
  oneof value {
    // StringValue represents a property that has a string value type.
    StringValue string_value = 3;

    // IntValue represents a property that has an integer value type.
    IntValue int_value = 4;

    // BoolValue represents a property that has a boolean value type.
    BoolValue bool_value = 5;

    // DoubleValue represents a property that has a double value type.
    DoubleValue double_value = 6;
  }

  // `name` is the key string to identify the property in `Node`s & `Edge`s.
  // Examples: `ProjectId`, `Base/displayName` etc.
  string name = 1;

  // A human-readable description of the `PropertyType`, explaining its meaning,
  // purpose, and any constraints or expectations on its value.
  string description = 10;
}

// StringValue represents a property that has a string value type.
message StringValue {
  // OPTIONAL
  // Whether the property is repeated.
  bool repeated = 1;

  // OPTIONAL
  // Allowed values for the property. If provided, the property value must be
  // one of the allowed values.
  repeated string allowed_values = 2;
}

// IntValue represents a property that has an integer value type.
message IntValue {
  // OPTIONAL
  // Whether the property is repeated.
  bool repeated = 1;

  // OPTIONAL
  // Allowed values for the property. If provided, the property value must be
  // one of the allowed values.
  repeated int64 allowed_values = 2;
}

// BoolValue represents a property that has a boolean value type.
message BoolValue {
  // OPTIONAL
  // Whether the property is repeated.
  bool repeated = 1;

  // OPTIONAL
  // Allowed values for the property. If provided, the property value must be
  // one of the allowed values.
  repeated bool allowed_values = 2;
}

// DoubleValue represents a property that has a double value type.
message DoubleValue {
  // OPTIONAL
  // Whether the property is repeated.
  bool repeated = 1;

  // OPTIONAL
  // Allowed values for the property. If provided, the property value must be
  // one of the allowed values.
  repeated double allowed_values = 2;
}
