syntax = "proto3";
package base.v1;

import "base/v1/base.proto";
import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";

option go_package = "github.com/Permify/permify/pkg/pb/base/v1";
// ** PERMISSION SERVICE **
// Permission service contains methods to interact with permissions.
service Permission {
  // Check method receives a PermissionCheckRequest and returns a PermissionCheckResponse.
  // It is used to determine whether a specific user has permission to perform an action on a resource.
  // For example, "Can the user 1 push to repository 1?"
  rpc Check(PermissionCheckRequest) returns (PermissionCheckResponse) {
    // HTTP mapping for this method
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/permissions/check"
      body: "*"
    };
    // OpenAPI annotations for this method
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "check api"
      tags: ["Permission"]
      operation_id: "permissions.check"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "cr, err := client.Permission.Check(context.Background(), &v1.PermissionCheckRequest {\n"
                      "    TenantId: \"t1\",\n"
                      "    Metadata: &v1.PermissionCheckRequestMetadata {\n"
                      "        SnapToken: \"\",\n"
                      "        SchemaVersion: \"\",\n"
                      "        Depth: 20,\n"
                      "    },\n"
                      "    Entity: &v1.Entity {\n"
                      "        Type: \"repository\",\n"
                      "        Id: \"1\",\n"
                      "    },\n"
                      "    Permission: \"edit\",\n"
                      "    Subject: &v1.Subject {\n"
                      "        Type: \"user\",\n"
                      "        Id: \"1\",\n"
                      "    },\n"
                      "})\n"
                      "if cr.Can == v1.PermissionCheckResponse_Result_RESULT_ALLOWED {\n"
                      "    // RESULT_ALLOWED\n"
                      "} else {\n"
                      "    // RESULT_DENIED\n"
                      "}"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.permission.check({\n"
                      "    tenantId: \"t1\", \n"
                      "    metadata: {\n"
                      "        snapToken: \"\",\n"
                      "        schemaVersion: \"\",\n"
                      "        depth: 20\n"
                      "    },\n"
                      "    entity: {\n"
                      "        type: \"repository\",\n"
                      "        id: \"1\"\n"
                      "    },\n"
                      "    permission: \"edit\",\n"
                      "    subject: {\n"
                      "        type: \"user\",\n"
                      "        id: \"1\"\n"
                      "    }\n"
                      "}).then((response) => {\n"
                      "    if (response.can === PermissionCheckResponse_Result.RESULT_ALLOWED) {\n"
                      "        console.log(\"RESULT_ALLOWED\")\n"
                      "    } else {\n"
                      "        console.log(\"RESULT_DENIED\")\n"
                      "    }\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/permissions/check' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "  \"metadata\": {\n"
                      "    \"snap_token\": \"\",\n"
                      "    \"schema_version\": \"\",\n"
                      "    \"depth\": 20\n"
                      "  },\n"
                      "  \"entity\": {\n"
                      "    \"type\": \"repository\",\n"
                      "    \"id\": \"1\"\n"
                      "  },\n"
                      "  \"permission\": \"edit\",\n"
                      "  \"subject\": {\n"
                      "    \"type\": \"user\",\n"
                      "    \"id\": \"1\",\n"
                      "    \"relation\": \"\"\n"
                      "  }\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // Expand method receives a PermissionExpandRequest and returns a PermissionExpandResponse.
  // It expands relationships according to the schema provided.
  rpc Expand(PermissionExpandRequest) returns (PermissionExpandResponse) {
    // HTTP mapping for this method
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/permissions/expand"
      body: "*"
    };
    // OpenAPI annotations for this method
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "expand api"
      tags: ["Permission"]
      operation_id: "permissions.expand"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "cr, err := client.Permission.Expand(context.Background(), &v1.PermissionExpandRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Metadata: &v1.PermissionExpandRequestMetadata{\n"
                      "        SnapToken: \"\",\n"
                      "        SchemaVersion: \"\",\n"
                      "    },\n"
                      "    Entity: &v1.Entity{\n"
                      "        Type: \"repository\",\n"
                      "        Id: \"1\",\n"
                      "    },\n"
                      "    Permission: \"push\",\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.permission.expand({\n"
                      "    tenantId: \"t1\",\n"
                      "    metadata: {\n"
                      "        snapToken: \"\",\n"
                      "        schemaVersion: \"\"\n"
                      "    },\n"
                      "    entity: {\n"
                      "        type: \"repository\",\n"
                      "        id: \"1\"\n"
                      "    },\n"
                      "    permission: \"push\",\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/permissions/expand' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "  \"metadata\": {\n"
                      "    \"schema_version\": \"\",\n"
                      "    \"snap_token\": \"\"\n"
                      "  },\n"
                      "  \"entity\": {\n"
                      "    \"type\": \"repository\",\n"
                      "    \"id\": \"1\"\n"
                      "  },\n"
                      "  \"permission\": \"push\"\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // LookupEntity method receives a PermissionLookupEntityRequest and returns a PermissionLookupEntityResponse.
  // It is used to retrieve an entity by its identifier.
  rpc LookupEntity(PermissionLookupEntityRequest) returns (PermissionLookupEntityResponse) {
    // HTTP mapping for this method
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/permissions/lookup-entity"
      body: "*"
    };
    // OpenAPI annotations for this method
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "lookup entity"
      tags: ["Permission"]
      operation_id: "permissions.lookupEntity"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "cr, err := client.Permission.LookupEntity(context.Background(), &v1.PermissionLookupEntityRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Metadata: &v1.PermissionLookupEntityRequestMetadata{\n"
                      "        SnapToken: \"\",\n"
                      "        SchemaVersion: \"\",\n"
                      "        Depth: 20,\n"
                      "    },\n"
                      "    EntityType: \"document\",\n"
                      "    Permission: \"edit\",\n"
                      "    Subject: &v1.Subject{\n"
                      "        Type: \"user\",\n"
                      "        Id: \"1\",\n"
                      "    }\n"
                      "    PageSize: 20,\n"
                      "    ContinuousToken: \"\",\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.permission.lookupEntity({\n"
                      "    tenantId: \"t1\",\n"
                      "    metadata: {\n"
                      "        snapToken: \"\",\n"
                      "        schemaVersion: \"\",\n"
                      "        depth: 20\n"
                      "    },\n"
                      "    entity_type: \"document\",\n"
                      "    permission: \"edit\",\n"
                      "    subject: {\n"
                      "        type: \"user\",\n"
                      "        id: \"1\"\n"
                      "    },\n"
                      "    page_size: 20,\n"
                      "    continuous_token: \"\"\n"
                      "}).then((response) => {\n"
                      "    console.log(response.entity_ids)\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/permissions/lookup-entity' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "  \"metadata\":{\n"
                      "    \"snap_token\": \"\",\n"
                      "    \"schema_version\": \"\",\n"
                      "    \"depth\": 20\n"
                      "  },\n"
                      "  \"entity_type\": \"document\",\n"
                      "  \"permission\": \"edit\",\n"
                      "  \"subject\": {\n"
                      "    \"type\":\"user\",\n"
                      "    \"id\":\"1\"\n"
                      "  },\n"
                      "  \"page_size\": 20,\n"
                      "  \"continuous_token\": \"\",\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // LookupEntityStream method receives a PermissionLookupEntityRequest and streams a series of PermissionLookupEntityStreamResponse messages.
  // It is used to retrieve entities by their identifiers in a streaming fashion.
  rpc LookupEntityStream(PermissionLookupEntityRequest) returns (stream PermissionLookupEntityStreamResponse) {
    // HTTP mapping for this method
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/permissions/lookup-entity-stream"
      body: "*"
    };
    // OpenAPI annotations for this method
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "lookup entity stream"
      tags: ["Permission"]
      operation_id: "permissions.lookupEntityStream"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "str, err := client.Permission.LookupEntityStream(context.Background(), &v1.PermissionLookupEntityRequest{\n"
                      "    Metadata: &v1.PermissionLookupEntityRequestMetadata{\n"
                      "        SnapToken: \"\",\n"
                      "        SchemaVersion: \"\",\n"
                      "        Depth: 50,\n"
                      "    },\n"
                      "    EntityType: \"document\",\n"
                      "    Permission: \"view\",\n"
                      "    Subject: &v1.Subject{\n"
                      "        Type: \"user\",\n"
                      "        Id: \"1\",\n"
                      "    },\n"
                      "    PageSize: 20,\n"
                      "    ContinuousToken: \"\",\n"
                      "})\n\n"
                      "// handle stream response\n"
                      "for {\n"
                      "    res, err := str.Recv()\n\n"
                      "    if err == io.EOF {\n"
                      "        break\n"
                      "    }\n\n"
                      "    // res.EntityId\n"
                      "}"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "const permify = require(\"@permify/permify-node\");\n"
                      "const {PermissionLookupEntityStreamResponse} = require(\"@permify/permify-node/dist/src/grpc/generated/base/v1/service\");\n\n"
                      "function main() {\n"
                      "    const client = new permify.grpc.newClient({\n"
                      "        endpoint: \"localhost:3478\",\n"
                      "    });\n\n"
                      "    let res = client.permission.lookupEntityStream({\n"
                      "        metadata: {\n"
                      "            snapToken: \"\",\n"
                      "            schemaVersion: \"\",\n"
                      "            depth: 20\n"
                      "        },\n"
                      "        entityType: \"document\",\n"
                      "        permission: \"view\",\n"
                      "        subject: {\n"
                      "            type: \"user\",\n"
                      "            id: \"1\"\n"
                      "        },\n"
                      "        page_size: 20,\n"
                      "        continuous_token: \"\"\n"
                      "    });\n\n"
                      "    handle(res);\n"
                      "}\n\n"
                      "async function handle(res: AsyncIterable<PermissionLookupEntityStreamResponse>) {\n"
                      "    for await (const response of res) {\n"
                      "        // response.entityId\n"
                      "    }\n"
                      "}"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // LookupSubject method receives a PermissionLookupSubjectRequest and returns a PermissionLookupSubjectResponse.
  // It is used to retrieve a subject by its identifier.
  rpc LookupSubject(PermissionLookupSubjectRequest) returns (PermissionLookupSubjectResponse) {
    // HTTP mapping for this method
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/permissions/lookup-subject"
      body: "*"
    };
    // OpenAPI annotations for this method
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "lookup-subject"
      tags: ["Permission"]
      operation_id: "permissions.lookupSubject"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "cr, err := client.Permission.LookupSubject(context.Background(), &v1.PermissionLookupSubjectRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Metadata: &v1.PermissionLookupSubjectRequestMetadata{\n"
                      "        SnapToken: \"\",\n"
                      "        SchemaVersion: \"\",\n"
                      "        Depth: 20,\n"
                      "    },\n"
                      "    Entity: &v1.Entity{\n"
                      "        Type: \"document\",\n"
                      "        Id: \"1\",\n"
                      "    },\n"
                      "    Permission: \"edit\",\n"
                      "    SubjectReference: &v1.RelationReference{\n"
                      "        Type: \"user\",\n"
                      "        Relation: \"\",\n"
                      "    },\n"
                      "    PageSize: 20,\n"
                      "    ContinuousToken: \"\",\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.permission.lookupSubject({\n"
                      "    tenantId: \"t1\",\n"
                      "    metadata: {\n"
                      "        snapToken: \"\",\n"
                      "        schemaVersion: \"\",\n"
                      "        depth: 20,\n"
                      "    },\n"
                      "    entity: {\n"
                      "        type: \"document\",\n"
                      "        id: \"1\",\n"
                      "    },\n"
                      "    permission: \"edit\",\n"
                      "    subject_reference: {\n"
                      "        type: \"user\",\n"
                      "        relation: \"\"\n"
                      "    },\n"
                      "    page_size: 10,\n"
                      "    continuous_token: \"\"\n"
                      "}).then((response) => {\n"
                      "    console.log(response.subject_ids)\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/permissions/lookup-subject' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "  \"metadata\":{\n"
                      "    \"snap_token\": \"\",\n"
                      "    \"schema_version\": \"\",\n"
                      "    \"depth\": 20,\n"
                      "  },\n"
                      "  \"entity\": {\n"
                      "    \"type\": \"document\",\n"
                      "    \"id\": \"1\"\n"
                      "  },\n"
                      "  \"permission\": \"edit\",\n"
                      "  \"subject_reference\": {\n"
                      "    \"type\": \"user\",\n"
                      "    \"relation\": \"\"\n"
                      "  },\n"
                      "   page_size: 20,\n"
                      "   continuous_token: \"\"\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // SubjectPermission method receives a PermissionSubjectPermissionRequest and returns a PermissionSubjectPermissionResponse.
  // It is used to retrieve permissions related to a specific subject.
  rpc SubjectPermission(PermissionSubjectPermissionRequest) returns (PermissionSubjectPermissionResponse) {
    // HTTP mapping for this method
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/permissions/subject-permission"
      body: "*"
    };
    // OpenAPI annotations for this method
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "subject permission"
      tags: ["Permission"]
      operation_id: "permissions.subjectPermission"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "cr, err := client.Permission.SubjectPermission(context.Background(), &v1.PermissionSubjectPermissionRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Metadata: &v1.PermissionSubjectPermissionRequestMetadata{\n"
                      "        SnapToken: \"\",\n"
                      "        SchemaVersion: \"\",\n"
                      "        OnlyPermission: false,\n"
                      "        Depth: 20,\n"
                      "    },\n"
                      "    Entity: &v1.Entity{\n"
                      "        Type: \"repository\",\n"
                      "        Id: \"1\",\n"
                      "    },\n"
                      "    Subject: &v1.Subject{\n"
                      "        Type: \"user\",\n"
                      "        Id: \"1\",\n"
                      "    },\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.permission.subjectPermission({\n"
                      "    tenantId: \"t1\",\n"
                      "    metadata: {\n"
                      "        snapToken: \"\",\n"
                      "        schemaVersion: \"\",\n"
                      "        onlyPermission: true,\n"
                      "        depth: 20\n"
                      "    },\n"
                      "    entity: {\n"
                      "        type: \"repository\",\n"
                      "        id: \"1\"\n"
                      "    },\n"
                      "    subject: {\n"
                      "        type: \"user\",\n"
                      "        id: \"1\"\n"
                      "    }\n"
                      "}).then((response) => {\n"
                      "    console.log(response);\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/permissions/subject-permission' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "  \"metadata\":{\n"
                      "    \"snap_token\": \"\",\n"
                      "    \"schema_version\": \"\",\n"
                      "    \"only_permission\": true,\n"
                      "    \"depth\": 20\n"
                      "  },\n"
                      "  \"entity\": {\n"
                      "    \"type\": \"repository\",\n"
                      "    \"id\": \"1\"\n"
                      "  },\n"
                      "  \"subject\": {\n"
                      "    \"type\": \"user\",\n"
                      "    \"id\": \"1\",\n"
                      "    \"relation\": \"\"\n"
                      "  }\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }
}

// CHECK

// PermissionCheckRequest is the request message for the Check method in the Permission service.
message PermissionCheckRequest {
  // Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // Metadata associated with this request, required.
  PermissionCheckRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];

  // Entity on which the permission needs to be checked, required.
  Entity entity = 3 [
    json_name = "entity",
    (validate.rules).message.required = true,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {example: "\"repository:1\""}
  ];

  // Name of the permission or relation, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes.
  string permission = 4 [
    json_name = "permission",
    (validate.rules).string = {
      pattern: "^[a-zA-Z_]{1,64}$"
      max_bytes: 64
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The action the user wants to perform on the resource"}
  ];

  // Subject for which the permission needs to be checked, required.
  Subject subject = 5 [
    json_name = "subject",
    (validate.rules).message.required = true
  ];

  // Context associated with this request.
  Context context = 6 [
    json_name = "context",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Contextual data that can be dynamically added to permission check requests. See details on [Contextual Data](../../operations/contextual-tuples)"}
  ];

  // Additional arguments associated with this request.
  repeated Argument arguments = 7 [json_name = "arguments"];
}

// PermissionCheckRequestMetadata metadata for the PermissionCheckRequest.
message PermissionCheckRequestMetadata {
  // Version of the schema.
  string schema_version = 1 [json_name = "schema_version"];

  // Token associated with the snap.
  string snap_token = 2 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)"}
  ];

  // Depth of the check, must be greater than or equal to 3.
  int32 depth = 3 [
    json_name = "depth",
    (validate.rules).int32.gte = 3,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Query limit when if recursive database queries got in loop"}
  ];
}

// PermissionCheckResponse is the response message for the Check method in the Permission service.
message PermissionCheckResponse {
  // Result of the permission check.
  CheckResult can = 1 [json_name = "can"];

  // Metadata associated with this response.
  PermissionCheckResponseMetadata metadata = 2 [json_name = "metadata"];
}

// PermissionCheckResponseMetadata metadata for the PermissionCheckResponse.
message PermissionCheckResponseMetadata {
  // The count of the checks performed.
  int32 check_count = 1 [json_name = "check_count"];
}

// EXPAND

// PermissionExpandRequest is the request message for the Expand method in the Permission service.
message PermissionExpandRequest {
  // Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // Metadata associated with this request, required.
  PermissionExpandRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];

  // Entity on which the permission needs to be expanded, required.
  Entity entity = 3 [
    json_name = "entity",
    (validate.rules).message.required = true
  ];

  // Name of the permission to be expanded, not required, must start with a letter and can include alphanumeric and underscore, max 64 bytes.
  string permission = 4 [
    json_name = "permission",
    (validate.rules).string = {
      pattern: "^[a-zA-Z_]{1,64}$"
      max_bytes: 64
      ignore_empty: true
    }
  ];

  // Context associated with this request.
  Context context = 5 [json_name = "context"];

  // Additional arguments associated with this request.
  repeated Argument arguments = 6 [json_name = "arguments"];
}

// PermissionExpandRequestMetadata metadata for the PermissionExpandRequest.
message PermissionExpandRequestMetadata {
  // Version of the schema.
  string schema_version = 1 [json_name = "schema_version"];

  // Token associated with the snap.
  string snap_token = 2 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)."}
  ];
}

// PermissionExpandResponse is the response message for the Expand method in the Permission service.
message PermissionExpandResponse {
  // Expansion tree.
  Expand tree = 1 [json_name = "tree"];
}

// LOOKUP ENTITY

// PermissionLookupEntityRequest is the request message for the LookupEntity method in the Permission service.
message PermissionLookupEntityRequest {
  // Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // Metadata associated with this request, required.
  PermissionLookupEntityRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];

  // Type of the entity to lookup, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes.
  string entity_type = 3 [
    json_name = "entity_type",
    (validate.rules).string = {
      pattern: "^[a-zA-Z_]{1,64}$"
      max_bytes: 64
      ignore_empty: false
    }
  ];

  // Name of the permission to check, required, must start with a letter and can include alphanumeric and underscore, max 64 bytes.
  string permission = 4 [
    json_name = "permission",
    (validate.rules).string = {
      pattern: "^[a-zA-Z_]{1,64}$"
      max_bytes: 64
      ignore_empty: false
    }
  ];

  // Subject for which to check the permission, required.
  Subject subject = 5 [
    json_name = "subject",
    (validate.rules).message.required = true
  ];

  // Context associated with this request.
  Context context = 6 [json_name = "context"];

  // Scope: A map that associates entity types with lists of identifiers. Each entry
  // helps filter requests by specifying which entities are relevant to the operation.
  map<string, StringArrayValue> scope = 7 [json_name = "scope"];

  // page_size is the number of entities to be returned in the response.
  // The value should be between 1 and 100.
  uint32 page_size = 8 [
    json_name = "page_size",
    (validate.rules).uint32 = {
      gte: 1
      ignore_empty: true
    }
  ];

  // continuous_token is an optional parameter used for pagination.
  // It should be the value received in the previous response.
  string continuous_token = 9 [
    json_name = "continuous_token",
    (validate.rules).string = {ignore_empty: true}
  ];
}

// PermissionLookupEntityRequestMetadata metadata for the PermissionLookupEntityRequest.
message PermissionLookupEntityRequestMetadata {
  // Version of the schema.
  string schema_version = 1 [json_name = "schema_version"];

  // Token associated with the snap.
  string snap_token = 2 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)."}
  ];

  // Depth of lookup, required, must be greater or equal to 3.
  int32 depth = 3 [
    json_name = "depth",
    (validate.rules).int32.gte = 3,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Query limit when if recursive database queries got in loop."}
  ];
}

// PermissionLookupEntityResponse is the response message for the LookupEntity method in the Permission service.
message PermissionLookupEntityResponse {
  // List of identifiers for entities that match the lookup.
  repeated string entity_ids = 1 [json_name = "entity_ids"];

  // continuous_token is a string that can be used to paginate and retrieve the next set of results.
  string continuous_token = 2 [json_name = "continuous_token"];
}

// LOOKUP STREAM

// PermissionLookupEntityStreamResponse is the response message for the LookupEntityStream method in the Permission service.
message PermissionLookupEntityStreamResponse {
  // Identifier for an entity that matches the lookup.
  string entity_id = 1 [json_name = "entity_id"];

  // continuous_token is a string that can be used to paginate and retrieve the next set of results.
  string continuous_token = 2 [json_name = "continuous_token"];
}

// PermissionEntityFilterRequest is the request message for the LookupEntityStream method in the Permission service.
message PermissionEntityFilterRequest {
  // Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // Metadata associated with this request, required.
  PermissionEntityFilterRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];

  // Reference to the entity to filter.
  Entrance entrance = 3 [json_name = "entrance"];

  // Subject for which to check the permission.
  Subject subject = 4 [json_name = "subject"];

  // Context associated with this request.
  Context context = 5 [json_name = "context"];

  // Scope: A map that associates entity types with lists of identifiers. Each entry
  // helps filter requests by specifying which entities are relevant to the operation.
  map<string, StringArrayValue> scope = 6 [json_name = "scope"];

  // cursor is an optional parameter used for pagination.
  // It should be the value received in the previous response.
  string cursor = 7 [
    json_name = "cursor",
    (validate.rules).string = {ignore_empty: true}
  ];
}

// PermissionEntityFilterRequestMetadata metadata for the PermissionEntityFilterRequest.
message PermissionEntityFilterRequestMetadata {
  // Version of the schema.
  string schema_version = 1 [json_name = "schema_version"];

  // Token associated with the snap.
  string snap_token = 2 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)."}
  ];

  // Depth of lookup, required, must be greater or equal to 3.
  int32 depth = 3 [
    json_name = "depth",
    (validate.rules).int32.gte = 3,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Query limit when if recursive database queries got in loop."}
  ];
}

// LOOKUP SUBJECT

// PermissionLookupSubjectRequest is the request message for the LookupSubject method in the Permission service.
message PermissionLookupSubjectRequest {
  // Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // Metadata associated with this request, required.
  PermissionLookupSubjectRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];

  // Entity for which to check the permission, required.
  Entity entity = 3 [
    json_name = "entity",
    (validate.rules).message.required = true
  ];

  // Permission to be checked, can be a permission or relation. Required, and must match the pattern "^([a-zA-Z][a-zA-Z0-9_]{1,62}[a-zA-Z0-9])$", max 64 bytes.
  string permission = 4 [
    json_name = "permission",
    (validate.rules).string = {
      pattern: "^[a-zA-Z_]{1,64}$"
      max_bytes: 64
      ignore_empty: false
    }
  ];

  // Reference to the subject to lookup.
  RelationReference subject_reference = 5 [
    json_name = "subject_reference",
    (validate.rules).message.required = true
  ];

  // Context associated with this request.
  Context context = 6 [json_name = "context"];

  // Additional arguments associated with this request.
  repeated Argument arguments = 7 [json_name = "arguments"];

  // page_size is the number of subjects to be returned in the response.
  // The value should be between 1 and 100.
  uint32 page_size = 8 [
    json_name = "page_size",
    (validate.rules).uint32 = {
      gte: 1
      ignore_empty: true
    }
  ];

  // continuous_token is an optional parameter used for pagination.
  // It should be the value received in the previous response.
  string continuous_token = 9 [
    json_name = "continuous_token",
    (validate.rules).string = {ignore_empty: true}
  ];
}

// PermissionLookupSubjectRequestMetadata metadata for the PermissionLookupSubjectRequest.
message PermissionLookupSubjectRequestMetadata {
  // Version of the schema.
  string schema_version = 1 [json_name = "schema_version"];

  // Token associated with the snap.
  string snap_token = 2 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)."}
  ];

  // Depth of the check, must be greater than or equal to 3.
  int32 depth = 3 [
    json_name = "depth",
    (validate.rules).int32.gte = 3,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Query limit when if recursive database queries got in loop."}
  ];
}

// PermissionLookupSubjectResponse is the response message for the LookupSubject method in the Permission service.
message PermissionLookupSubjectResponse {
  // List of identifiers for subjects that match the lookup.
  repeated string subject_ids = 1 [json_name = "subject_ids"];

  // continuous_token is a string that can be used to paginate and retrieve the next set of results.
  string continuous_token = 2 [json_name = "continuous_token"];
}

// SUBJECT PERMISSION

// PermissionSubjectPermissionRequest is the request message for the SubjectPermission method in the Permission service.
message PermissionSubjectPermissionRequest {
  // Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // Metadata associated with this request, required.
  PermissionSubjectPermissionRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];

  // Entity for which to check the permission, required.
  Entity entity = 3 [
    json_name = "entity",
    (validate.rules).message.required = true
  ];

  // Subject for which to check the permission, required.
  Subject subject = 4 [
    json_name = "subject",
    (validate.rules).message.required = true
  ];

  // Context associated with this request.
  Context context = 5 [json_name = "context"];
}

// PermissionSubjectPermissionRequestMetadata metadata for the PermissionSubjectPermissionRequest.
message PermissionSubjectPermissionRequestMetadata {
  // Version of the schema.
  string schema_version = 1 [json_name = "schema_version"];

  // Token associated with the snap.
  string snap_token = 2 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)."}
  ];

  // Whether to only check permissions.
  bool only_permission = 3 [json_name = "only_permission"];

  // Depth of the check, must be greater than or equal to 3.
  int32 depth = 4 [
    json_name = "depth",
    (validate.rules).int32.gte = 3,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Query limit when if recursive database queries got in loop."}
  ];
}

// PermissionSubjectPermissionResponse is the response message for the SubjectPermission method in the Permission service.
message PermissionSubjectPermissionResponse {
  // Map of results for each permission check.
  map<string, CheckResult> results = 1 [json_name = "results"];
}

// ** WATCH SERVICE **

// Watch service provides a streaming RPC that can be used to watch changes in the data.

// Watch is the main RPC in the Watch service. It establishes a stream between
// the client and the server. The server pushes data changes into this stream
// and the client can read those in real time.
service Watch {
  rpc Watch(WatchRequest) returns (stream WatchResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/watch" // HTTP mapping: POST request to the /v1/tenants/{tenant_id}/watch endpoint.
      body: "*" // The entire request message will be the HTTP request body.
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "watch changes" // Short summary of what the operation does.
      tags: [
        "Watch" // Adds an additional categorization for the operation.
      ]
      operation_id: "watch.watch" // Unique string used to identify the operation.
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "cr, err := client.Watch.Watch(context.Background(), &v1.WatchRequest{\n"
                      "    TenantId:  \"t1\",\n"
                      "    SnapToken: \"\",\n"
                      "})\n"
                      "// handle stream response\n"
                      "for {\n"
                      "    res, err := cr.Recv()\n\n"
                      "    if err == io.EOF {\n"
                      "        break\n"
                      "    }\n\n"
                      "    // res.Changes\n"
                      "}\n"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "const permify = require(\"@permify/permify-node\");\n"
                      "const {WatchResponse} = require(\"@permify/permify-node/dist/src/grpc/generated/base/v1/service\");\n\n"
                      "function main() {\n"
                      "    const client = new permify.grpc.newClient({\n"
                      "        endpoint: \"localhost:3478\",\n"
                      "    });\n\n"
                      "    let res = client.watch.watch({\n"
                      "        tenantId: \"t1\",\n"
                      "        snapToken: \"\"\n"
                      "    });\n\n"
                      "    handle(res);\n"
                      "}\n\n"
                      "async function handle(res: AsyncIterable<WatchResponse>) {\n"
                      "    for await (const response of res) {\n"
                      "        // response.changes\n"
                      "    }\n"
                      "}\n"
}
                }
              }
            }
          }
        }
      }
    };
  }
}

// WatchRequest is the request message for the Watch RPC. It contains the
// details needed to establish a watch stream.
message WatchRequest {
  // Identifier of the tenant, required, and must match the pattern "[a-zA-Z0-9-,]+", max 64 bytes.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // Snap token to be used for watching.
  string snap_token = 2 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)."}
  ];
}

// WatchResponse is the response message for the Watch RPC. It contains the
// changes in the data that are being watched.
message WatchResponse {
  // Changes in the data.
  DataChanges changes = 1 [json_name = "changes"];
}

// ** SCHEMA SERVICE **

// Schema service provides methods to manage the authorization model of your application.
// It allows you to read and write the schema of your authorization model.

// The Schema service definition.
service Schema {
  // Write is an RPC that allows you to write your authorization model.
  rpc Write(SchemaWriteRequest) returns (SchemaWriteResponse) {
    // It maps to HTTP POST requests and the entire request message
    // will be treated as the HTTP request body.
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/schemas/write" // HTTP mapping: POST request to the /v1/tenants/{tenant_id}/schemas/write endpoint.
      body: "*" // The entire request message will be the HTTP request body.
    };

    // OpenAPI specific annotation
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "write schema" // Short summary of what the operation does.
      tags: ["Schema"] /* Adds an additional categorization for the operation. */
      operation_id: "schemas.write" // Unique string used to identify the operation.
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "sr, err := client.Schema.Write(context.Background(), &v1.SchemaWriteRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Schema: `\n"
                      "    entity user {}\n\n"
                      "    entity organization {\n"
                      "        relation admin @user\n"
                      "        relation member @user\n\n"
                      "        action create_repository = (admin or member)\n"
                      "        action delete = admin\n"
                      "    }\n\n"
                      "    entity repository {\n"
                      "        relation owner @user\n"
                      "        relation parent @organization\n\n"
                      "        action push = owner\n"
                      "        action read = (owner and (parent.admin and parent.member))\n"
                      "        action delete = (parent.member and (parent.admin or owner))\n"
                      "    }\n"
                      "    `,\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.schema.write({\n"
                      "    tenantId: \"t1\",\n"
                      "    schema: `\n"
                      "    entity user {}\n\n"
                      "    entity organization {\n"
                      "        relation admin @user\n"
                      "        relation member @user\n\n"
                      "        action create_repository = (admin or member)\n"
                      "        action delete = admin\n"
                      "    }\n\n"
                      "    entity repository {\n"
                      "        relation owner @user\n"
                      "        relation parent @organization\n\n"
                      "        action push = owner\n"
                      "        action read = (owner and (parent.admin and parent.member))\n"
                      "        action delete = (parent.member and (parent.admin or owner))\n"
                      "    }\n"
                      "    `\n"
                      "}).then((response) => {\n"
                      "    // handle response\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/schemas/write' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "    \"schema\": \"entity user {}\\n\\n    entity organization {\\n\\n        relation admin @user\\n        relation member @user\\n\\n        action create_repository = (admin or member)\\n        action delete = admin\\n    }\\n\\n    entity repository {\\n\\n        relation owner @user\\n        relation parent @organization\\n\\n        action push = owner\\n        action read = (owner and (parent.admin and parent.member))\\n        action delete = (parent.member and (parent.admin or owner))\\n }\"\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // PartialWrite is an RPC that allows you to partially update an existing authorization model.
  rpc PartialWrite(SchemaPartialWriteRequest) returns (SchemaPartialWriteResponse) {
    // It maps to HTTP PATCH requests and the entire request message
    // will be treated as the HTTP request body.
    option (google.api.http) = {
      patch: "/v1/tenants/{tenant_id}/schemas/partial-write" // HTTP mapping: PATCH request to the /v1/tenants/{tenant_id}/schemas/partial-write endpoint.
      body: "*" // The entire request message will be the HTTP request body
    };

    // OpenAPI specific annotation
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "partially update your authorization model" // Short summary of what the operation does.
      tags: ["Schema"] /* Adds an additional categorization for the operation. */
      operation_id: "schemas.partial-write" // Unique string used to identify the operation.
    };
  }

  // Read is an RPC that allows you to read your authorization model.
  rpc Read(SchemaReadRequest) returns (SchemaReadResponse) {
    // It maps to HTTP POST requests and the entire request message
    // will be treated as the HTTP request body.
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/schemas/read" // HTTP mapping: POST request to the /v1/tenants/{tenant_id}/schemas/read endpoint.
      body: "*" // The entire request message will be the HTTP request body.
    };

    // OpenAPI specific annotation
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "read schema" // Short summary of what the operation does.
      tags: ["Schema"] /* Adds an additional categorization for the operation. */
      operation_id: "schemas.read" // Unique string used to identify the operation.
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "sr, err := client.Schema.Read(context.Background(), &v1.SchemaReadRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Metadata: &v1.SchemaReadRequestMetadata{\n"
                      "        SchemaVersion: \"cnbe6se5fmal18gpc66g\",\n"
                      "    },\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "let res = client.schema.read({\n"
                      "    tenantId: \"t1\",\n"
                      "    metadata: {\n"
                      "        schemaVersion: swResponse.schemaVersion,\n"
                      "    },\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/schemas/read' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "    \"metadata\": {\n"
                      "        \"schema_version\": \"cnbe6se5fmal18gpc66g\"\n"
                      "    }\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // List is an RPC that allows you to list all authorization models.
  rpc List(SchemaListRequest) returns (SchemaListResponse) {
    // It maps to HTTP POST requests and the entire request message
    // wil be treated as the HTTP request body.
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/schemas/list" // HTTP mapping: POST request to the /v1/tenants/{tenant_id}/schemas/list endpoint.
      body: "*"
    };

    // OpenAPI specific annotation.
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "list schema" // Short summary of what the operation does.
      tags: ["Schema"] /* Adds an additional categorization for the operation. */
      operation_id: "schemas.list" // Unique string used to identify the operation.
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "sr, err := client.Schema.List(context.Background(), &v1.SchemaListRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    PageSize: 20,\n"
                      "    ContinuousToken: \"\",\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "let res = client.schema.list({\n"
                      "    tenantId: \"t1\",\n"
                      "    continuousToken: \"\"\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: { // cURL example for listing schemas
                  key: "source" // Source code example
                  value: {string_value: // cURL command string
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/schemas/list' \\\n" // List schemas endpoint
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "    \"page_size\": 20,\n"
                      "    \"continuous_token\": \"\"\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }
}

// WRITE

// SchemaWriteRequest is the request message for the Write method in the Schema service.
// It contains tenant_id and the schema to be written.
message SchemaWriteRequest {
  // tenant_id is a string that identifies the tenant. It must match the pattern "[a-zA-Z0-9-,]+",
  // be a maximum of 64 bytes, and must not be empty.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // schema is the string representation of the schema to be written.
  string schema = 2 [json_name = "schema"];
}

// SchemaWriteResponse is the response message for the Write method in the Schema service.
// It returns the version of the written schema.
message SchemaWriteResponse {
  // schema_version is the string that identifies the version of the written schema.
  string schema_version = 1 [json_name = "schema_version"];
}

// PARTIAL WRITE

// It contains the tenant_id to identify the tenant and metadata of the schema to be edited,
// with the corresponding edits to various entities
message SchemaPartialWriteRequest {
  // tenant_id is a string that identifies the tenant. It must match the pattern "[a-zA-Z0-9-,]+",
  // be a maximum of 64 bytes, and must not be empty.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    }
  ];

  // metadata is the additional information needed for the Partial Write request.
  SchemaPartialWriteRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];

  // Map of entity name with the values needed to be updated
  map<string, Partials> partials = 3 [json_name = "partials"];
}

// SchemaPartialWriteRequestMetadata provides additional information for the Schema Partial Write request.
// It contains schema_version to specify which version of the schema should be read.
message SchemaPartialWriteRequestMetadata {
  // schema_version is the string that identifies the version of the schema to be read.
  string schema_version = 1 [json_name = "schema_version"];
}

// SchemaPartialWriteResponse is the response message for the Parietal Write method in the Schema service.
// It returns the requested schema.
message SchemaPartialWriteResponse {
  // schema_version is the string that identifies the version of the written schema.
  string schema_version = 1 [json_name = "schema_version"];
}

// READ

// SchemaReadRequest is the request message for the Read method in the Schema service.
// It contains tenant_id and metadata about the schema to be read.
message SchemaReadRequest {
  // tenant_id is a string that identifies the tenant. It must match the pattern "[a-zA-Z0-9-,]+",
  // be a maximum of 64 bytes, and must not be empty.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // metadata is the additional information needed for the Read request.
  SchemaReadRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];
}

// SchemaReadRequestMetadata provides additional information for the Schema Read request.
// It contains schema_version to specify which version of the schema should be read.
message SchemaReadRequestMetadata {
  // schema_version is the string that identifies the version of the schema to be read.
  string schema_version = 1 [json_name = "schema_version"];
}

// SchemaReadResponse is the response message for the Read method in the Schema service.
// It returns the requested schema.
message SchemaReadResponse {
  // schema is the SchemaDefinition that represents the read schema.
  SchemaDefinition schema = 1 [json_name = "schema"];
}

// LIST

// SchemaListRequest is the request message for the List method in the Schema service.
// It contains tenant_id for which the schemas are to be listed.
message SchemaListRequest {
  // tenant_id is a string that identifies the tenant. It must match the pattern "[a-zA-Z0-9-,]+",
  // be a maximum of 64 bytes, and must not be empty.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // page_size is the number of schemas to be returned in the response.
  // The value should be between 1 and 100.
  uint32 page_size = 2 [
    json_name = "page_size",
    (validate.rules).uint32 = {
      gte: 1
      ignore_empty: true
    }
  ];

  // continuous_token is an optional parameter used for pagination.
  // It should be the value received in the previous response.
  string continuous_token = 3 [
    json_name = "continuous_token",
    (validate.rules).string = {ignore_empty: true}
  ];
}

// SchemaListResponse is the response message for the List method in the Schema service.
// It returns a paginated list of schemas
message SchemaListResponse {
  // head of the schemas is the latest version available for the tenant
  string head = 1 [json_name = "head"];
  // list of schema versions with creation timestamps
  repeated SchemaList schemas = 2 [json_name = "schemas"];
  // continuous_token is a string that can be used to paginate and retrieve the next set of results.
  string continuous_token = 3 [json_name = "continuous_token"];
}

// SchemaList provides a list of schema versions with their corresponding creation timestamps
message SchemaList {
  string version = 1 [json_name = "version"];
  string created_at = 2 [json_name = "created_at"];
}

// ** DATA SERVICE **

// The Data service provides RPC methods for managing data in the context of relationships and attributes.
service Data {
  // The Write RPC method creates a new relation tuple.
  rpc Write(DataWriteRequest) returns (DataWriteResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/data/write"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "write data"
      tags: ["Data"]
      operation_id: "data.write"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "// Convert the wrapped attribute value into Any proto message\n"
                      "value, err := anypb.New(&v1.BooleanValue{\n"
                      "    Data: true,\n"
                      "})\n"
                      "if err != nil {\n"
                      "    // Handle error\n"
                      "}\n\n"
                      "cr, err := client.Data.Write(context.Background(), &v1.DataWriteRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Metadata: &v1.DataWriteRequestMetadata{\n"
                      "        SchemaVersion: \"\",\n"
                      "    },\n"
                      "    Tuples: []*v1.Tuple{\n"
                      "        {\n"
                      "            Entity: &v1.Entity{\n"
                      "                Type: \"document\",\n"
                      "                Id:   \"1\",\n"
                      "            },\n"
                      "            Relation: \"editor\",\n"
                      "            Subject:  &v1.Subject{\n"
                      "                Type: \"user\",\n"
                      "                Id:   \"1\",\n"
                      "                Relation: \"\",\n"
                      "            },\n"
                      "        },\n"
                      "    },\n"
                      "    Attributes: []*v1.Attribute{\n"
                      "        {\n"
                      "            Entity: &v1.Entity{\n"
                      "                Type: \"document\",\n"
                      "                Id:   \"1\",\n"
                      "            },\n"
                      "            Attribute: \"is_private\",\n"
                      "            Value:     value,\n"
                      "        },\n"
                      "    },\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "const booleanValue = BooleanValue.fromJSON({ data: true });\n\n"
                      "const value = Any.fromJSON({\n"
                      "    typeUrl: 'type.googleapis.com/base.v1.BooleanValue',\n"
                      "    value: BooleanValue.encode(booleanValue).finish()\n"
                      "});\n\n"
                      "client.data.write({\n"
                      "    tenantId: \"t1\",\n"
                      "    metadata: {\n"
                      "        schemaVersion: \"\"\n"
                      "    },\n"
                      "    tuples: [{\n"
                      "        entity: {\n"
                      "            type: \"document\",\n"
                      "            id: \"1\"\n"
                      "        },\n"
                      "        relation: \"editor\",\n"
                      "        subject: {\n"
                      "            type: \"user\",\n"
                      "            id: \"1\"\n"
                      "        }\n"
                      "    }],\n"
                      "    attributes: [{\n"
                      "        entity: {\n"
                      "            type: \"document\",\n"
                      "            id: \"1\"\n"
                      "        },\n"
                      "        attribute: \"is_private\",\n"
                      "        value: value,\n"
                      "    }]\n"
                      "}).then((response) => {\n"
                      "    // handle response\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/data/write' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "    \"metadata\": {\n"
                      "        \"schema_version\": \"\"\n"
                      "    },\n"
                      "    \"tuples\": [\n"
                      "        {\n"
                      "            \"entity\": {\n"
                      "                \"type\": \"document\",\n"
                      "                \"id\": \"1\"\n"
                      "            },\n"
                      "            \"relation\": \"editor\",\n"
                      "            \"subject\": {\n"
                      "                \"type\": \"user\",\n"
                      "                \"id\": \"1\"\n"
                      "            }\n"
                      "        }\n"
                      "    ],\n"
                      "    \"attributes\": [\n"
                      "        {\n"
                      "            \"entity\": {\n"
                      "                \"type\": \"document\",\n"
                      "                \"id\": \"1\"\n"
                      "            },\n"
                      "            \"attribute\": \"is_private\",\n"
                      "            \"value\": {\n"
                      "                \"@type\": \"type.googleapis.com/base.v1.BooleanValue\",\n"
                      "                \"data\": true\n"
                      "            }\n"
                      "        }\n"
                      "    ]\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // RPC method to write relationships for a tenant. This can be accessed via a POST request to the given HTTP path. It's tagged under "Data" in OpenAPI documentation.
  rpc WriteRelationships(RelationshipWriteRequest) returns (RelationshipWriteResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/relationships/write"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "write relationships"
      tags: ["Data"]
      operation_id: "relationships.write"
    };
  }

  // The ReadRelationships RPC method reads relation tuple(s).
  rpc ReadRelationships(RelationshipReadRequest) returns (RelationshipReadResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/data/relationships/read"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "read relationships"
      tags: ["Data"]
      operation_id: "data.relationships.read"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "rr, err := client.Data.ReadRelationships(context.Background(), &v1.Data.RelationshipReadRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Metadata: &v1.Data.RelationshipReadRequestMetadata{\n"
                      "        SnapToken: \"\"\n"
                      "    },\n"
                      "    Filter: &v1.TupleFilter{\n"
                      "        Entity: &v1.EntityFilter{\n"
                      "            Type: \"organization\",\n"
                      "            Ids: []string{\"1\"},\n"
                      "        },\n"
                      "        Relation: \"member\",\n"
                      "        Subject: &v1.SubjectFilter{\n"
                      "            Type: \"\",\n"
                      "            Id: []string{\"\"},\n"
                      "            Relation: \"\"\n"
                      "        }\n"
                      "    }\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.data.readRelationships({\n"
                      "  tenantId: \"t1\",\n"
                      "  metadata: {\n"
                      "    snap_token: \"\",\n"
                      "  },\n"
                      "  filter: {\n"
                      "    entity: {\n"
                      "      type: \"organization\",\n"
                      "      ids: [\n"
                      "        \"1\"\n"
                      "      ]\n"
                      "    },\n"
                      "    relation: \"member\",\n"
                      "    subject: {\n"
                      "      type: \"\",\n"
                      "      ids: [],\n"
                      "      relation: \"\"\n"
                      "    }\n"
                      "  }\n"
                      "}).then((response) => {\n"
                      "  // handle response\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/data/relationships/read' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "  metadata: {\n"
                      "    snap_token: \"\",\n"
                      "  },\n"
                      "  filter: {\n"
                      "    entity: {\n"
                      "      type: \"organization\",\n"
                      "      ids: [\n"
                      "        \"1\"\n"
                      "      ]\n"
                      "    },\n"
                      "    relation: \"member\",\n"
                      "    subject: {\n"
                      "      type: \"\",\n"
                      "      ids: [],\n"
                      "      relation: \"\"\n"
                      "    }\n"
                      "  }\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // The ReadAttributes RPC method reads attribute(s) of a relation.
  rpc ReadAttributes(AttributeReadRequest) returns (AttributeReadResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/data/attributes/read"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "read attributes"
      tags: ["Data"]
      operation_id: "data.attributes.read"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "rr, err := client.Data.ReadAttributes(context.Background(), &v1.Data.AttributeReadRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Metadata: &v1.Data.AttributeReadRequestMetadata{\n"
                      "        SnapToken: \"\",\n"
                      "    },\n"
                      "    Filter: &v1.AttributeFilter{\n"
                      "        Entity: &v1.EntityFilter{\n"
                      "            Type: \"organization\",\n"
                      "            Ids: []string{\"1\"},\n"
                      "        },\n"
                      "        Attributes: []string{\"private\"},\n"
                      "    },\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.data.readAttributes({\n"
                      "  tenantId: \"t1\",\n"
                      "  metadata: {\n"
                      "    snap_token: \"\",\n"
                      "  },\n"
                      "  filter: {\n"
                      "    entity: {\n"
                      "      type: \"organization\",\n"
                      "      ids: [\n"
                      "        \"1\"\n"
                      "      ]\n"
                      "    },\n"
                      "    attributes: [\n"
                      "      \"private\"\n"
                      "    ],\n"
                      "  }\n"
                      "}).then((response) => {\n"
                      "  // handle response\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/data/attributes/read' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "  metadata: {\n"
                      "    snap_token: \"\",\n"
                      "  },\n"
                      "  filter: {\n"
                      "    entity: {\n"
                      "      type: \"organization\",\n"
                      "      ids: [\n"
                      "        \"1\"\n"
                      "      ]\n"
                      "    },\n"
                      "    attributes: [\n"
                      "      \"private\"\n"
                      "    ],\n"
                      "  }\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // The Delete RPC method deletes a relation tuple.
  rpc Delete(DataDeleteRequest) returns (DataDeleteResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/data/delete"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "delete data"
      tags: ["Data"]
      operation_id: "data.delete"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "rr, err := client.Data.Delete(context.Background(), &v1.DataDeleteRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Metadata: &v1.DataDeleteRequestMetadata{\n"
                      "        SnapToken: \"\",\n"
                      "    },\n"
                      "    TupleFilter: &v1.TupleFilter{\n"
                      "        Entity: &v1.EntityFilter{\n"
                      "            Type: \"organization\",\n"
                      "            Ids: []string{\"1\"},\n"
                      "        },\n"
                      "        Relation: \"admin\",\n"
                      "        Subject: &v1.SubjectFilter{\n"
                      "            Type: \"user\",\n"
                      "            Id: []string{\"1\"},\n"
                      "            Relation: \"\"\n"
                      "        }\n"
                      "    }\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.data.delete({\n"
                      "  tenantId: \"t1\",\n"
                      "  metadata: {\n"
                      "    snap_token: \"\",\n"
                      "  },\n"
                      "  tupleFilter: {\n"
                      "    entity: {\n"
                      "      type: \"organization\",\n"
                      "      ids: [\n"
                      "        \"1\"\n"
                      "      ]\n"
                      "    },\n"
                      "    relation: \"admin\",\n"
                      "    subject: {\n"
                      "      type: \"user\",\n"
                      "      ids: [\n"
                      "        \"1\"\n"
                      "      ],\n"
                      "      relation: \"\"\n"
                      "    }\n"
                      "  }\n"
                      "}).then((response) => {\n"
                      "  // handle response\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/data/delete' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "  \"tuple_filter\": {\n"
                      "    \"entity\": {\n"
                      "      \"type\": \"organization\",\n"
                      "      \"ids\": [\n"
                      "        \"1\"\n"
                      "      ]\n"
                      "    },\n"
                      "    \"relation\": \"admin\",\n"
                      "    \"subject\": {\n"
                      "      \"type\": \"user\",\n"
                      "      \"ids\": [\n"
                      "        \"1\"\n"
                      "      ],\n"
                      "      \"relation\": \"\"\n"
                      "    }\n"
                      "  },\n"
                      "  \"attribute_filter\": {}\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // RPC method to delete relationships for a tenant, accessed via a POST request to the specified path, tagged as "Data" in OpenAPI documentation.
  rpc DeleteRelationships(RelationshipDeleteRequest) returns (RelationshipDeleteResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/relationships/delete"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "delete relationships"
      tags: ["Data"]
      operation_id: "relationships.delete"
    };
  }

  // Executes or runs a specific bundle. This method is useful for processing or triggering actions based on the bundle's data.
  rpc RunBundle(BundleRunRequest) returns (BundleRunResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/data/run-bundle"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "run bundle"
      tags: ["Data"]
      operation_id: "bundle.run"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "rr, err := client.Data.RunBundle(context.Background(), &v1.BundleRunRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Name:     \"organization_created\",\n"
                      "    Arguments: map[string]string{\n"
                      "        \"creatorID\":      \"564\",\n"
                      "        \"organizationID\": \"789\",\n"
                      "    },\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.data.runBundle({\n"
                      "    tenantId: \"t1\",\n"
                      "    name: \"organization_created\",\n"
                      "    arguments: {\n"
                      "        creatorID: \"564\",\n"
                      "        organizationID: \"789\",\n"
                      "    }\n"
                      "}).then((response) => {\n"
                      "    // handle response\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/data/run-bundle' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "    \"name\": \"organization_created\",\n"
                      "    \"arguments\": {\n"
                      "        \"creatorID\": \"564\",\n"
                      "        \"organizationID\": \"789\"\n"
                      "    }\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }
}

// DataWriteRequest defines the structure of a request for writing data.
// It contains the necessary information such as tenant_id, metadata,
// tuples and attributes for the write operation.
message DataWriteRequest {
  // tenant_id represents the unique identifier of the tenant for which data is written.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // metadata holds additional data related to the request.
  DataWriteRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];

  // tuples contains the list of tuples (entity-relation-entity triples) that need to be written.
  repeated Tuple tuples = 3 [
    json_name = "tuples",
    (validate.rules).repeated = {
      min_items: 0
      items: {
        message: {required: true}
      }
    }
  ];

  // attributes contains the list of attributes (entity-attribute-value triples) that need to be written.
  repeated Attribute attributes = 4 [
    json_name = "attributes",
    (validate.rules).repeated = {
      min_items: 0
      items: {
        message: {required: true}
      }
    }
  ];
}

// DataWriteRequestMetadata defines the structure of metadata for a write request.
// It includes the schema version of the data to be written.
message DataWriteRequestMetadata {
  // schema_version represents the version of the schema for the data being written.
  string schema_version = 1 [json_name = "schema_version"];
}

// DataWriteResponse defines the structure of the response after writing data.
// It contains the snap_token generated after the write operation.
message DataWriteResponse {
  // snap_token is the token generated after the data write operation, representing a snapshot of the data.
  string snap_token = 1 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)."}
  ];
}

// Represents a request to write relationship data.
message RelationshipWriteRequest {
  // Unique identifier for the tenant with specific constraints.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // Metadata for the request. It's required.
  RelationshipWriteRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];

  // List of tuples for the request. Must have between 1 and 100 items.
  repeated Tuple tuples = 3 [
    json_name = "tuples",
    (validate.rules).repeated = {
      min_items: 1
      items: {
        message: {required: true}
      }
    }
  ];
}

// RelationshipWriteRequestMetadata
message RelationshipWriteRequestMetadata {
  string schema_version = 1 [json_name = "schema_version"];
}

// RelationshipWriteResponse
message RelationshipWriteResponse {
  string snap_token = 1 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)"}
  ];
}

// RelationshipReadRequest defines the structure of a request for reading relationships.
// It contains the necessary information such as tenant_id, metadata, and filter for the read operation.
message RelationshipReadRequest {
  // tenant_id represents the unique identifier of the tenant for which relationships are read.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // metadata holds additional data related to the request.
  RelationshipReadRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];

  // filter is used to specify criteria for the data that needs to be read.
  TupleFilter filter = 3 [
    json_name = "filter",
    (validate.rules).message.required = true
  ];

  // page_size specifies the number of results to return in a single page.
  // If more results are available, a continuous_token is included in the response.
  uint32 page_size = 4 [
    json_name = "page_size",
    (validate.rules).uint32 = {
      gte: 1
      ignore_empty: true
    }
  ];

  // continuous_token is used in case of paginated reads to get the next page of results.
  string continuous_token = 5 [
    json_name = "continuous_token",
    (validate.rules).string = {ignore_empty: true}
  ];
}

// RelationshipReadRequestMetadata defines the structure of the metadata for a read request focused on relationships.
// It includes the snap_token associated with a particular state of the database.
message RelationshipReadRequestMetadata {
  // snap_token represents a specific state or "snapshot" of the database.
  string snap_token = 1 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)"}
  ];
}

// RelationshipReadResponse defines the structure of the response after reading relationships.
// It includes the tuples representing the relationships and a continuous token for handling result pagination.
message RelationshipReadResponse {
  // tuples is a list of the relationships retrieved in the read operation, represented as entity-relation-entity triples.
  repeated Tuple tuples = 1 [json_name = "tuples"];

  // continuous_token is used in the case of paginated reads to retrieve the next page of results.
  string continuous_token = 2 [json_name = "continuous_token"];
}

// AttributeReadRequest defines the structure of a request for reading attributes.
// It includes the tenant_id, metadata, attribute filter, page size for pagination, and a continuous token for multi-page results.
message AttributeReadRequest {
  // tenant_id represents the unique identifier of the tenant from which the attributes are being read.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // metadata holds additional information related to the request.
  AttributeReadRequestMetadata metadata = 2 [
    json_name = "metadata",
    (validate.rules).message.required = true
  ];

  // filter specifies the criteria used to select the attributes that should be returned.
  AttributeFilter filter = 3 [
    json_name = "filter",
    (validate.rules).message.required = true
  ];

  // page_size specifies the number of results to return in a single page.
  // If more results are available, a continuous_token is included in the response.
  uint32 page_size = 4 [
    json_name = "page_size",
    (validate.rules).uint32 = {
      gte: 1
      ignore_empty: true
    }
  ];

  // continuous_token is used in case of paginated reads to get the next page of results.
  string continuous_token = 5 [
    json_name = "continuous_token",
    (validate.rules).string = {ignore_empty: true}
  ];
}

// AttributeReadRequestMetadata defines the structure for the metadata of an attribute read request.
// It includes the snap_token associated with a particular state of the database.
message AttributeReadRequestMetadata {
  // snap_token represents a specific state or "snapshot" of the database.
  string snap_token = 1 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)"}
  ];
}

// AttributeReadResponse defines the structure of the response to an attribute read request.
// It includes the attributes retrieved and a continuous token for handling result pagination.
message AttributeReadResponse {
  // attributes is a list of the attributes retrieved in the read operation.
  repeated Attribute attributes = 1 [json_name = "attributes"];

  // continuous_token is used in the case of paginated reads to retrieve the next page of results.
  string continuous_token = 2 [json_name = "continuous_token"];
}

// DataDeleteRequest defines the structure of a request to delete data.
// It includes the tenant_id and filters for selecting tuples and attributes to be deleted.
message DataDeleteRequest {
  // tenant_id represents the unique identifier of the tenant from which the data will be deleted.
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // tuple_filter specifies the criteria used to select the tuples that should be deleted.
  TupleFilter tuple_filter = 2 [
    json_name = "tuple_filter",
    (validate.rules).message.required = true
  ];

  // attribute_filter specifies the criteria used to select the attributes that should be deleted.
  AttributeFilter attribute_filter = 3 [
    json_name = "attribute_filter",
    (validate.rules).message.required = true
  ];
}

// DataDeleteResponse defines the structure of the response to a data delete request.
// It includes a snap_token representing the state of the database after the deletion.
message DataDeleteResponse {
  // snap_token represents the state of the database after the requested deletions.
  string snap_token = 1 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)"}
  ];
}

// RelationshipDeleteRequest
message RelationshipDeleteRequest {
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  TupleFilter filter = 2 [json_name = "filter"];
}

// RelationshipDeleteResponse
message RelationshipDeleteResponse {
  string snap_token = 1 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)"}
  ];
}

// BundleRunRequest is used to request the execution of a bundle.
// It includes tenant_id, the name of the bundle, and additional arguments for execution.
message BundleRunRequest {
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  // Name of the bundle to be executed.
  string name = 2 [json_name = "name"];

  // Additional key-value pairs for execution arguments.
  map<string, string> arguments = 3 [json_name = "arguments"];
}

// BundleRunResponse is the response for a BundleRunRequest.
// It includes a snap_token, which may be used for tracking the execution or its results.
message BundleRunResponse {
  string snap_token = 1 [
    json_name = "snap_token",
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The snap token to avoid stale cache, see more details on [Snap Tokens](../../operations/snap-tokens)"}
  ];
}

// ** BUNDLE SERVICE **

service Bundle {
  // Writes a bundle of data for a specific operation. This is a general purpose method to handle writing data bundles.
  rpc Write(BundleWriteRequest) returns (BundleWriteResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/bundle/write"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "write bundle"
      tags: ["Bundle"]
      operation_id: "bundle.write"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "rr, err := client.Bundle.Write(context.Background(), &v1.BundleWriteRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Bundles: []*v1.DataBundle{\n"
                      "        {\n"
                      "            Name: \"organization_created\",\n"
                      "            Arguments: []string{\n"
                      "                \"creatorID\",\n"
                      "                \"organizationID\",\n"
                      "            },\n"
                      "            Operations: []*v1.Operation{\n"
                      "                {\n"
                      "                    RelationshipsWrite: []string{\n"
                      "                        \"organization:{{.organizationID}}#admin@user:{{.creatorID}}\",\n"
                      "                        \"organization:{{.organizationID}}#manager@user:{{.creatorID}}\",\n"
                      "                    },\n"
                      "                    AttributesWrite: []string{\n"
                      "                        \"organization:{{.organizationID}}$public|boolean:false\",\n"
                      "                    },\n"
                      "                },\n"
                      "            },\n"
                      "        },\n"
                      "    },\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.bundle.write({\n"
                      "    tenantId: \"t1\",\n"
                      "    bundles: [\n"
                      "        {\n"
                      "            name: \"organization_created\",\n"
                      "            arguments: [\n"
                      "                \"creatorID\",\n"
                      "                \"organizationID\",\n"
                      "            ],\n"
                      "            operations: [\n"
                      "                {\n"
                      "                    relationships_write: [\n"
                      "                        \"organization:{{.organizationID}}#admin@user:{{.creatorID}}\",\n"
                      "                        \"organization:{{.organizationID}}#manager@user:{{.creatorID}}\",\n"
                      "                    ],\n"
                      "                    attributes_write: [\n"
                      "                        \"organization:{{.organizationID}}$public|boolean:false\",\n"
                      "                    ]\n"
                      "                }\n"
                      "            ]\n"
                      "        }\n"
                      "    ]\n"
                      "}).then((response) => {\n"
                      "    // handle response\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/bundle/write' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "    \"bundles\": [\n"
                      "        {\n"
                      "            \"name\": \"organization_created\",\n"
                      "            \"arguments\": [\n"
                      "                \"creatorID\",\n"
                      "                \"organizationID\"\n"
                      "            ],\n"
                      "            \"operations\": [\n"
                      "                {\n"
                      "                    \"relationships_write\": [\n"
                      "                        \"organization:{{.organizationID}}#admin@user:{{.creatorID}}\",\n"
                      "                        \"organization:{{.organizationID}}#manager@user:{{.creatorID}}\"\n"
                      "                    ],\n"
                      "                    \"attributes_write\": [\n"
                      "                        \"organization:{{.organizationID}}$public|boolean:false\"\n"
                      "                    ]\n"
                      "                }\n"
                      "            ]\n"
                      "        }\n"
                      "    ]\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // Reads a data bundle based on a specified request. This method is tailored for retrieving data bundles.
  rpc Read(BundleReadRequest) returns (BundleReadResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/bundle/read"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "read bundle"
      tags: ["Bundle"]
      operation_id: "bundle.read"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "rr, err := client.Bundle.Read(context.Background(), &v1.BundleReadRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Name:     \"organization_created\",\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.bundle.read({\n"
                      "    tenantId: \"t1\",\n"
                      "    name: \"organization_created\",\n"
                      "}).then((response) => {\n"
                      "    // handle response\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/bundle/read' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "    \"name\": \"organization_created\"\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // Deletes a specific data bundle. This method is used to remove existing bundles from the system.
  rpc Delete(BundleDeleteRequest) returns (BundleDeleteResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/{tenant_id}/bundle/delete"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "delete bundle"
      tags: ["Bundle"]
      operation_id: "bundle.delete"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "rr, err := client.Bundle.Delete(context.Background(), &v1.BundleDeleteRequest{\n"
                      "    TenantId: \"t1\",\n"
                      "    Name:     \"organization_created\",\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.bundle.delete({\n"
                      "    tenantId: \"t1\",\n"
                      "    name: \"organization_created\",\n"
                      "}).then((response) => {\n"
                      "    // handle response\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/{tenant_id}/bundle/delete' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "    \"name\": \"organization_created\"\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }
}

// BundleWriteRequest is used to request the writing of a bundle.
// It contains the tenant_id to identify the tenant and the Bundles object.
message BundleWriteRequest {
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  repeated DataBundle bundles = 2; // Contains the bundle data to be written.
}

// BundleWriteResponse is the response for a BundleWriteRequest.
// It includes a name which could be used as an identifier or acknowledgment.
message BundleWriteResponse {
  repeated string names = 1 [json_name = "names"]; // Identifier or acknowledgment of the written bundle.
}

message BundleReadRequest {
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  string name = 2 [json_name = "name"];
}

message BundleReadResponse {
  DataBundle bundle = 1 [json_name = "bundle"];
}

// BundleDeleteRequest is used to request the deletion of a bundle.
// It contains the tenant_id to specify the tenant and the name of the bundle to be deleted.
message BundleDeleteRequest {
  string tenant_id = 1 [
    json_name = "tenant_id",
    (validate.rules).string = {
      pattern: "^([a-zA-Z0-9_\\-@\\.:+]{1,128}|\\*)$"
      max_bytes: 128
      ignore_empty: false
    },
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Identifier of the tenant, if you are not using multi-tenancy (have only one tenant) use pre-inserted tenant <code>t1</code> for this field. Required, and must match the pattern \\“[a-zA-Z0-9-,]+\\“, max 64 bytes."}
  ];

  string name = 2 [json_name = "name"]; // Name of the bundle to be deleted.
}

message BundleDeleteResponse {
  string name = 1 [json_name = "name"];
}

// ** TENANCY SERVICE **
// The Tenancy service defines the gRPC methods for managing tenants.

service Tenancy {
  // Create is a unary RPC to create a new tenant.
  // It requires a TenantCreateRequest and returns a TenantCreateResponse.
  rpc Create(TenantCreateRequest) returns (TenantCreateResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/create"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "create tenant"
      tags: ["Tenancy"]
      operation_id: "tenants.create"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "rr, err := client.Tenancy.Create(context.Background(), &v1.TenantCreateRequest{\n"
                      "    Id:   \"\",\n"
                      "    Name: \"\"\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.tenancy.create({\n"
                      "   id: \"\",\n"
                      "   name: \"\"\n"
                      "}).then((response) => {\n"
                      "    // handle response\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'http://localhost:3476/v1/tenants/create' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "    \"id\": \"\",\n"
                      "    \"name\": \"\"\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }

  // Delete is a unary RPC to delete an existing tenant.
  // It requires a TenantDeleteRequest and returns a TenantDeleteResponse.
  rpc Delete(TenantDeleteRequest) returns (TenantDeleteResponse) {
    option (google.api.http) = {delete: "/v1/tenants/{id}"};

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "delete tenant"
      tags: ["Tenancy"]
      operation_id: "tenants.delete"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "rr, err := client.Tenancy.Delete(context.Background(), &v1.TenantDeleteRequest{\n"
                      "    Id: \"\"\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "client.tenancy.delete({\n"
                      "   id: \"\",\n"
                      "}).then((response) => {\n"
                      "    // handle response\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value: "curl --location --request DELETE 'http://localhost:3476/v1/tenants/t1'"}
                }
              }
            }
          }
        }
      }
    };
  }

  // List is a unary RPC to get a list of all tenants.
  // It requires a TenantListRequest and returns a TenantListResponse.
  rpc List(TenantListRequest) returns (TenantListResponse) {
    option (google.api.http) = {
      post: "/v1/tenants/list"
      body: "*"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "list tenants"
      tags: ["Tenancy"]
      operation_id: "tenants.list"
      description: ""
      extensions: {
        key: "x-codeSamples"
        value: {
          list_value: {
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "go"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "cr, err := client.Tenancy.List(context.Background(), &v1.TenantListRequest{\n"
                      "    PageSize: 20,\n"
                      "    ContinuousToken: \"\",\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "javascript"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "node"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "let res = client.tenancy.list({\n"
                      "    pageSize: 20,\n"
                      "    continuousToken: \"\",\n"
                      "})"
}
                }
              }
            }
            values: {
              struct_value: {
                fields: {
                  key: "lang"
                  value: {string_value: "curl"}
                }
                fields: {
                  key: "label"
                  value: {string_value: "cURL"}
                }
                fields: {
                  key: "source"
                  value: {string_value:
                      "curl --location --request POST 'localhost:3476/v1/tenants/list' \\\n"
                      "--header 'Content-Type: application/json' \\\n"
                      "--data-raw '{\n"
                      "    \"page_size\": 20,\n"
                      "    \"continuous_token\": \"\"\n"
                      "}'"
}
                }
              }
            }
          }
        }
      }
    };
  }
}

// TenantCreateRequest is the message used for the request to create a tenant.
message TenantCreateRequest {
  // id is a unique identifier for the tenant.
  string id = 1 [
    json_name = "id",
    (validate.rules).string = {
      pattern: "[a-zA-Z0-9-,]+"
      max_bytes: 64
      ignore_empty: false
    }
  ];

  // name is the name of the tenant.
  string name = 2 [
    json_name = "name",
    (validate.rules).string = {
      max_bytes: 64
      ignore_empty: false
    }
  ];
}

// TenantCreateResponse is the message returned from the request to create a tenant.
message TenantCreateResponse {
  // tenant is the created tenant information.
  Tenant tenant = 1 [json_name = "tenant"];
}

// TenantDeleteRequest is the message used for the request to delete a tenant.
message TenantDeleteRequest {
  // id is the unique identifier of the tenant to be deleted.
  string id = 1 [
    json_name = "id",
    (validate.rules).string = {ignore_empty: false}
  ];
}

// TenantDeleteResponse is the message returned from the request to delete a tenant.
message TenantDeleteResponse {
  // tenant_id is the tenant id that was deleted.
  string tenant_id = 1 [json_name = "tenant_id"];
}

// TenantListRequest is the message used for the request to list all tenants.
message TenantListRequest {
  // page_size is the number of tenants to be returned in the response.
  // The value should be between 1 and 100.
  uint32 page_size = 1 [
    json_name = "page_size",
    (validate.rules).uint32 = {
      gte: 1
      ignore_empty: true
    }
  ];

  // continuous_token is an optional parameter used for pagination.
  // It should be the value received in the previous response.
  string continuous_token = 2 [
    json_name = "continuous_token",
    (validate.rules).string = {ignore_empty: true}
  ];
}

// TenantListResponse is the message returned from the request to list all tenants.
message TenantListResponse {
  // tenants is a list of tenants.
  repeated Tenant tenants = 1 [json_name = "tenants"];

  // continuous_token is a string that can be used to paginate and retrieve the next set of results.
  string continuous_token = 2 [json_name = "continuous_token"];
}
