// Copyright IBM Corp. 2020, 2026
// SPDX-License-Identifier: MPL-2.0

syntax = "proto3";

package controller.api.resources.sessionrecordings.v1;

import "controller/api/resources/scopes/v1/scope.proto";
import "controller/custom_options/v1/options.proto";
import "google/api/visibility.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";

option go_package = "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/session_recordings;session_recordings";

// ChannelRecording contains recorded information about a single Channel within a Connection.
// Channels are only present in multiplexed protocols, such as SSH.
message ChannelRecording {
  // The ID of the Channel recording.
  string id = 1; // @gotags: class:"public" eventstream:"observation"

  // The total number of bytes uploaded from the client in the Channel.
  uint64 bytes_up = 2 [json_name = "bytes_up"]; // @gotags: class:"public" eventstream:"observation"

  // The total number of bytes downloaded to the client in the Channel.
  uint64 bytes_down = 3 [json_name = "bytes_down"]; // @gotags: class:"public" eventstream:"observation"

  // The time the Channel was created in the controller.
  google.protobuf.Timestamp created_time = 4 [json_name = "created_time"]; // @gotags: class:"public" eventstream:"observation"

  // The time of the most recent update to the Channel.
  google.protobuf.Timestamp updated_time = 5 [json_name = "updated_time"]; // @gotags: class:"public" eventstream:"observation"

  // The time the Channel started.
  google.protobuf.Timestamp start_time = 6 [json_name = "start_time"]; // @gotags: class:"public" eventstream:"observation"

  // The time the Channel ended.
  google.protobuf.Timestamp end_time = 7 [json_name = "end_time"]; // @gotags: class:"public" eventstream:"observation"

  // The total duration of the Channel.
  google.protobuf.Duration duration = 8; // @gotags: class:"public" eventstream:"observation"

  // MimeTypes define the mime types that can
  // be used to consume the recording of this Channel.
  // The only supported mime type is "application/x-asciicast".
  repeated string mime_types = 9 [json_name = "mime_types"]; // @gotags: class:"public" eventstream:"observation"
}

// ConnectionRecording contains the recording of a single Connection within a Session.
message ConnectionRecording {
  // The ID of the Connection recording.
  string id = 1; // @gotags: class:"public" eventstream:"observation"

  // The total number of bytes uploaded from the client in the Connection.
  // This includes any protocol overhead.
  uint64 bytes_up = 2 [json_name = "bytes_up"]; // @gotags: class:"public" eventstream:"observation"

  // The total number of bytes downloaded to the client in the Connection.
  // This includes any protocol overhead.
  uint64 bytes_down = 3 [json_name = "bytes_down"]; // @gotags: class:"public" eventstream:"observation"

  // The time the Connection was created in the controller.
  google.protobuf.Timestamp created_time = 4 [json_name = "created_time"]; // @gotags: class:"public" eventstream:"observation"

  // The time of the most recent update to the Connection.
  google.protobuf.Timestamp updated_time = 5 [json_name = "updated_time"]; // @gotags: class:"public" eventstream:"observation"

  // The time the Connection started.
  google.protobuf.Timestamp start_time = 6 [json_name = "start_time"]; // @gotags: class:"public" eventstream:"observation"

  // The time the Connection ended.
  google.protobuf.Timestamp end_time = 7 [json_name = "end_time"]; // @gotags: class:"public" eventstream:"observation"

  // The total duration of the Connection.
  google.protobuf.Duration duration = 8; // @gotags: class:"public" eventstream:"observation"

  // MimeTypes define the mime types that can
  // be used to consume the recording of this Connection.
  // No mime types are currently supported.
  repeated string mime_types = 9 [json_name = "mime_types"]; // @gotags: class:"public"

  // Optionally, the channels used in this Connection,
  // if it is using a multiplexed protocol, such as SSH.
  repeated ChannelRecording channel_recordings = 10 [json_name = "channel_recordings"];
}

// User describes an authenticated user in Boundary.
message User {
  // The ID of the User.
  string id = 1; // @gotags: class:"public" eventstream:"observation"

  // The name of the User that created the Session.
  string name = 2; // @gotags: class:"sensitive"

  // The description of the User that created the Session.
  string description = 3; // @gotags: class:"sensitive"

  // The scope that the User is in.
  resources.scopes.v1.ScopeInfo scope = 7;
}

// HostCatalog describes the HostCatalog that contains the host chosen for the
// recorded session.
message HostCatalog {
  // The ID of the Host Catalog
  string id = 1; // @gotags: class:"public" eventstream:"observation"

  // The scope that the Host Catalog is in
  resources.scopes.v1.ScopeInfo scope = 2;

  // The plugin id used by this Host Catalog, if any.
  string plugin_id = 3 [json_name = "plugin_id"]; // @gotags: class:"public" eventstream:"observation"

  // The name of the Host Catalog, if set
  string name = 4; // @gotags: class:"public"

  // The description of the Host Catalog.
  string description = 5; // @gotags: class:"public"

  // The type of the Host Catalog.  This will be either "static" or "plugin"
  string type = 6; // @gotags: class:"public" eventstream:"observation"

  oneof attrs {
    // The attributes of the Host Catalog.
    google.protobuf.Struct attributes = 7; // @gotags: class:"public"
  }
}

// Host describes the Host that was chosen for the recorded session.
message Host {
  // The ID of the Host
  string id = 1; // @gotags: class:"public" eventstream:"observation"

  // The Host Catalog this Host is in
  HostCatalog host_catalog = 2 [json_name = "host_catalog"];

  // The name of the Host, if set.
  string name = 3; // @gotags: class:"public"

  // The description of the Host, if set.
  string description = 4; // @gotags: class:"public"

  // The type of the host. This will be either "static" or "plugin"
  string type = 5; // @gotags: class:"public" eventstream:"observation"

  oneof attrs {
    // Here we use the google.protobuf.Struct so the generated structs in
    // api/ are map[string]interface{}.  Future work will include having
    // well defined proto messages which contain exactly the fields expected
    // in the attributes depending on the type of this resource, similar to
    // how attributes are done when attributes is a top level field.

    // The attributes that are applicable for the specific Host.
    google.protobuf.Struct attributes = 6 [(custom_options.v1.subtype) = "default"];
    StaticHostAttributes static_host_attributes = 9 [
      (google.api.field_visibility).restriction = "INTERNAL",
      (custom_options.v1.subtype) = "static"
    ];
  }

  // The external id of the Host, if any.
  string external_id = 7 [json_name = "external_id"]; // @gotags: class:"public"

  // The external name of the Host, if any.
  string external_name = 8 [json_name = "external_name"]; // @gotags: class:"public"
}

message StaticHostAttributes {
  // The address specified on a static host
  string address = 1; // @gotags: class:"public"
}

// Target describes a target in Boundary.
message Target {
  // The ID of the Target.
  string id = 1; // @gotags: class:"public" eventstream:"observation"

  // The name of the Target, if set.
  string name = 2; // @gotags: class:"public"

  // The description of the Target, if set.
  string description = 3; // @gotags: class:"public"

  // The scope that the Target is in.
  resources.scopes.v1.ScopeInfo scope = 4;

  // Maximum total lifetime of a created Session, in seconds.
  uint32 session_max_seconds = 5 [json_name = "session_max_seconds"]; // @gotags: class:"public" eventstream:"observation"

  // Maximum number of connections allowed in a Session.  Unlimited is indicated by the value -1.
  int32 session_connection_limit = 6 [json_name = "session_connection_limit"]; // @gotags: class:"public" eventstream:"observation"

  // Optional boolean expression to filter the workers that are allowed to satisfy this request.
  string worker_filter = 7 [json_name = "worker_filter"]; // @gotags: class:"public"

  // Optional boolean expressions to filter the egress workers that are allowed to satisfy this request.
  string egress_worker_filter = 8 [json_name = "egress_worker_filter"]; // @gotags: class:"public"

  // Optional boolean expressions to filter the ingress workers that are allowed to satisfy this request.
  string ingress_worker_filter = 9 [json_name = "ingress_worker_filter"]; // @gotags: class:"public"

  // The type of the Target.
  string type = 10; // @gotags: class:"public" eventstream:"observation"

  oneof attrs {
    // Here we use the google.protobuf.Struct so the generated structs in
    // api/ are map[string]interface{}.  Future work will include having
    // well defined proto messages which contain exactly the fields expected
    // in the attributes depending on the type of this resource, similar to
    // how attributes are done when attributes is a top level field.

    // The attributes that are applicable for the specific Target.
    google.protobuf.Struct attributes = 11 [(custom_options.v1.subtype) = "default"];
    SshTargetAttributes ssh_target_attributes = 12 [
      (google.api.field_visibility).restriction = "INTERNAL",
      (custom_options.v1.subtype) = "ssh"
    ];
  }
}

// SshTargetAttributes contains attributes relevant to Targets of type "ssh"
message SshTargetAttributes {
  // The default SSH port that is used when connecting to the endpoint.
  uint32 default_port = 1 [json_name = "default_port"]; // @gotags: class:"public"

  // The default TCP port that will be listened on by the client's local proxy.
  uint32 default_client_port = 2 [json_name = "default_client_port"]; // @gotags: class:"public"
}

// CredentialStore contains all fields related to a Credential Store resource
message CredentialStore {
  // The ID of the Credential Store.
  string id = 1; // @gotags: class:"public" eventstream:"observation"

  // The ID of the Scope of which this Credential Store is a part.
  string scope_id = 2 [json_name = "scope_id"]; // @gotags: class:"public" eventstream:"observation"

  // The name for identification purposes if set.
  string name = 3; // @gotags: class:"public"

  // The description for identification purposes if set.
  string description = 4; // @gotags: class:"public"

  // The Credential Store type.
  string type = 5; // @gotags: class:"public" eventstream:"observation"

  oneof attrs {
    // The attributes that are applicable for the specific Credential Store type.
    google.protobuf.Struct attributes = 6 [(custom_options.v1.subtype) = "default"];
    VaultCredentialStoreAttributes vault_credential_store_attributes = 7 [
      (google.api.field_visibility).restriction = "INTERNAL",
      (custom_options.v1.subtype) = "vault"
    ];
  }
}

// The attributes of a vault typed Credential Store.
message VaultCredentialStoreAttributes {
  // The complete url address of vault.
  string address = 1; // @gotags: class:"public"

  // The namespace of vault used by this store
  string namespace = 2; // @gotags: class:"public"

  // The value to use as the SNI host when connecting to vault via TLS.
  string tls_server_name = 3 [json_name = "tls_server_name"]; // @gotags: class:"public"

  // Indicates if verification of the TLS certificate is disabled.
  bool tls_skip_verify = 4 [json_name = "tls_skip_verify"]; // @gotags: class:"public"

  // Filters to the worker(s) who can handle Vault requests for this cred store if set.
  string worker_filter = 5 [json_name = "worker_filter"]; // @gotags: class:"public"
}

// Credential contains fields related to an Credential resource
message Credential {
  // The ID of the Credential.
  string id = 1; // @gotags: class:"public" eventstream:"observation"

  // The Credential Store of which this Credential is a part.
  CredentialStore credential_store = 2 [json_name = "credential_store"];

  // The name of the credential.
  string name = 3; // @gotags: class:"public"

  // Optional user-set description.
  string description = 4; // @gotags: class:"public"

  // The purposes for which this Credential was attached to the sesssion.
  repeated string purposes = 5; // @gotags: class:"public"

  // The Credential type.
  string type = 6; // @gotags: class:"public" eventstream:"observation"

  oneof attrs {
    // The attributes that are applicable for the specific Credential type.
    google.protobuf.Struct attributes = 7 [(custom_options.v1.subtype) = "default"];
    UsernamePasswordCredentialAttributes username_password_attributes = 8 [
      (google.api.field_visibility).restriction = "INTERNAL",
      (custom_options.v1.subtype) = "username_password"
    ];
    SshPrivateKeyCredentialAttributes ssh_private_key_attributes = 9 [
      (google.api.field_visibility).restriction = "INTERNAL",
      (custom_options.v1.subtype) = "ssh_private_key"
    ];
    JsonCredentialAttributes json_attributes = 10 [
      (google.api.field_visibility).restriction = "INTERNAL",
      (custom_options.v1.subtype) = "json"
    ];
    PasswordCredentialAttributes password_attributes = 11 [
      (google.api.field_visibility).restriction = "INTERNAL",
      (custom_options.v1.subtype) = "password"
    ];
  }
}

// The attributes of a UsernamePassword Credential.
message UsernamePasswordCredentialAttributes {
  // The username associated with the credential.
  string username = 1; // @gotags: class:"sensitive"

  // The hmac value of the password.
  string password_hmac = 2; // @gotags: class:"public"
}

// The attributes of a SshPrivateKey Credential.
message SshPrivateKeyCredentialAttributes {
  // The username associated with the credential.
  string username = 1; // @gotags: class:"public"

  // The hmac value of the SSH private key.
  string private_key_hmac = 2; // @gotags: class:"public"

  // The hmac value of the SSH private key passphrase.
  string private_key_passphrase_hmac = 3; // @gotags: class:"public"
}

// The attributes of a JSON Credential.
message JsonCredentialAttributes {
  // The hmac value of the object.
  string object_hmac = 1; // @gotags: class:"public"
}

// The attributes of a Password Credential.
message PasswordCredentialAttributes {
  // The hmac value of the password.
  string password_hmac = 1; // @gotags: class:"public"
}

// CredentialLibrary contains all fields related to an Credential Library resource
message CredentialLibrary {
  // The ID of the Credential Library.
  string id = 1; // @gotags: class:"public" eventstream:"observation"

  // The credential store of which this library is a part.
  CredentialStore credential_store = 2 [json_name = "credential_store"];

  //  Optional name of this Credential Library.
  string name = 3; // @gotags: class:"public"

  // Optional user-set description of this Credential Library.
  string description = 4; // @gotags: class:"public"

  // The purposes for which this CredentialLibrary was attached to the sesssion.
  repeated string purposes = 5; // @gotags: class:"public"

  // The Credential Library type.
  string type = 6; // @gotags: class:"public" eventstream:"observation"

  oneof attrs {
    // The attributes that are applicable for the specific Credential Library type.
    google.protobuf.Struct attributes = 7 [(custom_options.v1.subtype) = "default"];
    VaultCredentialLibraryAttributes vault_credential_library_attributes = 8 [
      (google.api.field_visibility).restriction = "INTERNAL",
      (custom_options.v1.subtype) = "vault"
    ];
    VaultCredentialLibraryAttributes vault_generic_credential_library_attributes = 9 [
      (google.api.field_visibility).restriction = "INTERNAL",
      (custom_options.v1.subtype) = "vault-generic"
    ];
    VaultSSHCertificateCredentialLibraryAttributes vault_ssh_certificate_credential_library_attributes = 10 [
      (google.api.field_visibility).restriction = "INTERNAL",
      (custom_options.v1.subtype) = "vault-ssh-certificate"
    ];
  }
}

// The attributes of a vault typed Credential Library.
message VaultCredentialLibraryAttributes {
  // The path in Vault to request credentials from.
  string path = 1; // @gotags: class:"public"

  // The HTTP method the library uses to communicate with Vault.
  string http_method = 2; // @gotags: class:"public"

  // The body of the HTTP request the library sends to vault.
  string http_request_body = 3; // @gotags: `class:"secret"`
}

// The attributes of a vault SSH Certificate Credential Library.
message VaultSSHCertificateCredentialLibraryAttributes {
  // The path in Vault to request credentials from.
  string path = 1; // @gotags: class:"public"

  // The username used when making an SSH connection.
  string username = 2; // @gotags: `class:"sensitive"`

  // The key type to use when generating an SSH private key.
  string key_type = 3; // @gotags: class:"public"

  // The number of bits to use to generate an SSH private key.
  uint32 key_bits = 4; // @gotags: class:"public"

  // The requested time to live for the certificate.
  string ttl = 5; // @gotags: class:"public"

  // The critical options that the certificate should be signed for.
  map<string, string> critical_options = 6; // @gotags: class:"public"

  // The extensions that the certificate should be signed for.
  map<string, string> extensions = 7; // @gotags: class:"public"

  // Principals to be signed as "valid_principles" in addition to username.
  repeated string additional_valid_principals = 8; // @gotags: class:"public"
}

// ValuesAtTime contain information about other Boundary resources as they
// were at a certain time through the lifetime of the Session Recording.
message ValuesAtTime {
  // Information about the User that created the Session.
  User user = 1; // @gotags: class:"public"

  // Information about the Target the Session connected to.
  Target target = 2; // @gotags: class:"public"

  // Information about the Host chosen for the session.
  Host host = 3; // @gotags: class:"public"

  // Information about the Credentials used for this session.
  repeated Credential credentials = 4;

  // Information about the Credential Libraries used for this session.
  repeated CredentialLibrary credential_libraries = 5 [json_name = "credential_libraries"];
}

// SessionRecording contains information about the recording of a Session.
message SessionRecording {
  // The ID of the Session recording.
  string id = 1; // @gotags: class:"public"

  // The scope that the Session Recording is in.
  // This is inferred from the storage bucket associated
  // with the target.
  resources.scopes.v1.ScopeInfo scope = 2; // @gotags: class:"public"

  // The ID of the Session which this Session Recording recorded.
  string session_id = 3 [json_name = "session_id"]; // @gotags: class:"public" eventstream:"observation"

  // The ID of the Storage Bucket for the Target of this Session Recording.
  string storage_bucket_id = 4 [json_name = "storage_bucket_id"]; // @gotags: class:"public" eventstream:"observation"

  // The total number of bytes uploaded from the client in the Session.
  // This includes all bytes uploaded over all Connections, including
  // any protocol overhead.
  uint64 bytes_up = 5 [json_name = "bytes_up"]; // @gotags: class:"public" eventstream:"observation"

  // The total number of bytes downloaded to the client in the Session.
  // This includes all bytes downloaded over all Connections, including
  // any protocol overhead.
  uint64 bytes_down = 6 [json_name = "bytes_down"]; // @gotags: class:"public" eventstream:"observation"

  // The time the Session Recording was created in the controller.
  google.protobuf.Timestamp created_time = 7 [json_name = "created_time"]; // @gotags: class:"public" eventstream:"observation"

  // The time of the most recent update to the Session Recording.
  google.protobuf.Timestamp updated_time = 8 [json_name = "updated_time"]; // @gotags: class:"public" eventstream:"observation"

  // The time the Session started.
  google.protobuf.Timestamp start_time = 9 [json_name = "start_time"]; // @gotags: class:"public" eventstream:"observation"

  // The time the Session ended.
  google.protobuf.Timestamp end_time = 10 [json_name = "end_time"]; // @gotags: class:"public" eventstream:"observation"

  // The total duration of the Session.
  google.protobuf.Duration duration = 11; // @gotags: class:"public" eventstream:"observation"

  // Type of the Session that was recorded (e.g. ssh).
  string type = 12; // @gotags: class:"public" eventstream:"observation"

  // The current state of the session recording. One of
  // "started", "available" and "unknown".
  string state = 13; // @gotags: class:"public" eventstream:"observation"

  // Any error seen during the closing of the session recording.
  // Currently only set if state is "unknown".
  string error_details = 14; // @gotags: class:"public"

  // MimeTypes define the mime types that can
  // be used to consume the recording of this Session.
  // No mime types are currently supported.
  repeated string mime_types = 15 [json_name = "mime_types"]; // @gotags: class:"public" eventstream:"observation"

  // The endpoint of the Session; that is, the address to which the egress worker connected.
  string endpoint = 16; // @gotags: class:"public"

  // The recordings of the connections that were created in the Session.
  // This field may be unset when listing Session recordings.
  repeated ConnectionRecording connection_recordings = 17 [json_name = "connection_recordings"];

  // create_time_values contains the values of related fields at the time
  // this Session Recording was created. This may be unset when listing.
  ValuesAtTime create_time_values = 18 [json_name = "create_time_values"]; // @gotags: class:"public"

  // The available actions on this resource for this user.
  repeated string authorized_actions = 19 [json_name = "authorized_actions"]; // @gotags: class:"public"

  // The time until a session recording is required to be stored.
  google.protobuf.Timestamp retain_until = 20 [json_name = "retain_until"]; // @gotags: class:"public" eventstream:"observation"

  // The time a session recording is scheduled to be automatically deleted.
  google.protobuf.Timestamp delete_after = 21 [json_name = "delete_after"]; // @gotags: class:"public" eventstream:"observation"
}
