syntax = "proto3";

package hashicorp.waypoint;

option go_package = "pkg/server/gen";

import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "google/rpc/status.proto";
import "any.proto";

/********************************************************************
* PERMANENTLY RESERVED FIELD NUMBERS
* 100000000 - inline keepalives
********************************************************************/

// The service that is implemented for the server backend.
service Waypoint {
  //----------------------------------------------------------------------
  // Unauthenticated endpoints
  //----------------------------------------------------------------------

  // GetVersionInfo returns information about the server. This RPC call does
  // NOT require authentication. It can be used by clients to determine if they
  // are capable of talking to this server.
  rpc GetVersionInfo(google.protobuf.Empty) returns (GetVersionInfoResponse);

  // List the available OIDC providers for authentication. The "name" of the
  // OIDC provider can be used with GetOIDCAuthURL and CompleteOIDCAuth to
  // perform OIDC-based authentication.
  rpc ListOIDCAuthMethods(google.protobuf.Empty) returns (ListOIDCAuthMethodsResponse);

  // Get the URL to visit to start authentication with OIDC.
  rpc GetOIDCAuthURL(GetOIDCAuthURLRequest) returns (GetOIDCAuthURLResponse);

  // Complete the OIDC auth cycle after receiving the callback from the
  // OIDC provider.
  rpc CompleteOIDCAuth(CompleteOIDCAuthRequest) returns (CompleteOIDCAuthResponse);

  // Attempts to run a trigger given a trigger ID reference. If the trigger does
  // not exist, we return not found. If the trigger exists but requires authentication
  // we return an error.
  rpc NoAuthRunTrigger(RunTriggerRequest) returns (RunTriggerResponse);

  //----------------------------------------------------------------------
  // Authenticated endpoints for general API use.
  //----------------------------------------------------------------------

  // GetUser returns the current logged in user or some other user.
  rpc GetUser(GetUserRequest) returns (GetUserResponse);

  // List all users in the system.
  rpc ListUsers(google.protobuf.Empty) returns (ListUsersResponse);

  // Update the details about an existing user.
  rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse);

  // Delete a user. This will invalidate all authentication for this user
  // as well since they no longer exist.
  rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty);

  // UpsertAuthMethod upserts the auth method. All users logged in with
  // this auth method will remain logged in even if settings change.
  rpc UpsertAuthMethod(UpsertAuthMethodRequest) returns (UpsertAuthMethodResponse);

  // GetAuthMethod returns the auth method.
  rpc GetAuthMethod(GetAuthMethodRequest) returns (GetAuthMethodResponse);

  // ListAuthMethods returns a list of all the auth methods.
  rpc ListAuthMethods(google.protobuf.Empty) returns (ListAuthMethodsResponse);

  // Delete an auth method. This will invalidate all users authenticated
  // using this auth method and they will have to reauthenticate some other
  // way.
  rpc DeleteAuthMethod(DeleteAuthMethodRequest) returns (google.protobuf.Empty);

  // ListWorkspaces returns a list of all workspaces.
  //
  // Note that currently this list is never pruned, even if a workspace is
  // no longer in use. We plan to prune this in a future improvement.
  rpc ListWorkspaces(ListWorkspacesRequest) returns (ListWorkspacesResponse);

  // GetWorkspace returns the workspace.
  rpc GetWorkspace(GetWorkspaceRequest) returns (GetWorkspaceResponse);

  // UpsertWorkspace upserts the workspace. Changes to a Workspace's Projects
  // are ignored at this time.
  rpc UpsertWorkspace(UpsertWorkspaceRequest) returns (UpsertWorkspaceResponse);

  // UpsertProject upserts the project.
  rpc UpsertProject(UpsertProjectRequest) returns (UpsertProjectResponse);

  // GetProject returns the project.
  rpc GetProject(GetProjectRequest) returns (GetProjectResponse) {}

  // ListProjects returns a list of all the projects. There is no equivalent
  // ListApplications because applications are a part of projects and you
  // can use GetProject to get more information about the project.
  rpc ListProjects(google.protobuf.Empty) returns (ListProjectsResponse) {}

  // DestroyProject deletes a project from the database as well as (optionally)
  // destroys all resources created within a project
  rpc DestroyProject(DestroyProjectRequest) returns (google.protobuf.Empty) {};

  // GetApplication returns one application on the project.
  rpc GetApplication(GetApplicationRequest) returns (GetApplicationResponse);

  // UpsertApplication upserts an application with a project.
  rpc UpsertApplication(UpsertApplicationRequest) returns (UpsertApplicationResponse);

  // ListBuilds returns the builds.
  rpc ListBuilds(ListBuildsRequest) returns (ListBuildsResponse);

  // GetBuild returns a build
  rpc GetBuild(GetBuildRequest) returns (Build) {}

  // GetLatestBuild returns the most recent successfully completed build
  // for an app.
  rpc GetLatestBuild(GetLatestBuildRequest) returns (Build);

  // ListPushedArtifacts returns the builds.
  rpc ListPushedArtifacts(ListPushedArtifactsRequest) returns (ListPushedArtifactsResponse);

  // GetPushedArtifact returns a deployment
  rpc GetPushedArtifact(GetPushedArtifactRequest) returns (PushedArtifact);

  // GetLatestPushedArtifact returns the most recent successfully completed
  // artifact push for an app.
  rpc GetLatestPushedArtifact(GetLatestPushedArtifactRequest) returns (PushedArtifact);

  // ListDeployments returns the deployments.
  rpc ListDeployments(ListDeploymentsRequest) returns (ListDeploymentsResponse);

  // GetDeployment returns a deployment
  rpc GetDeployment(GetDeploymentRequest) returns (Deployment) {}

  // ListInstances returns the running instances of deployments.
  rpc ListInstances(ListInstancesRequest) returns (ListInstancesResponse);

  // ListReleases returns the releases.
  rpc ListReleases(ListReleasesRequest) returns (ListReleasesResponse);

  // GetRelease returns a release
  rpc GetRelease(GetReleaseRequest) returns (Release) {}

  // GetLatestRelease returns the most recent successfully completed
  // release for an app.
  rpc GetLatestRelease(GetLatestReleaseRequest) returns (Release);

  // GetStatusReport returns a StatusReport
  rpc GetStatusReport(GetStatusReportRequest) returns (StatusReport);

  // GetLatestStatusReport returns the most recent successfully completed
  // health report for an app
  rpc GetLatestStatusReport(GetLatestStatusReportRequest) returns (StatusReport);

  // ListStatusReports returns the deployments.
  rpc ListStatusReports(ListStatusReportsRequest) returns (ListStatusReportsResponse);

  // ExpediteStatusReport returns the queued status report job id
  rpc ExpediteStatusReport(ExpediteStatusReportRequest) returns (ExpediteStatusReportResponse);

  // GetLogStream reads the log stream for a deployment. This will immediately
  // send a single LogEntry with the lines we have so far. If there are no
  // available lines this will NOT block and instead will return an error.
  // The client can choose to retry or not.
  rpc GetLogStream(GetLogStreamRequest) returns (stream LogBatch);

  // StartExecStream starts an exec session.
  rpc StartExecStream(stream ExecStreamRequest) returns (stream ExecStreamResponse);

  // Set one or more configuration variables for applications or runners.
  rpc SetConfig(ConfigSetRequest) returns (ConfigSetResponse);

  // Retrieve merged configuration values for a specific scope. You can determine
  // where a configuration variable was set by looking at the scope field on
  // each variable.
  rpc GetConfig(ConfigGetRequest) returns (ConfigGetResponse);

  // Set the configuration for a dynamic configuration source. If you're looking
  // to set application configuration, you probably want SetConfig instead.
  rpc SetConfigSource(SetConfigSourceRequest) returns (google.protobuf.Empty);

  // Get the matching configuration source for the request. This will return
  // the most specific matching config source given the scope in the request.
  // For example, if you search for an app-specific config source and only
  // a global config exists, the global config will be returned.
  rpc GetConfigSource(GetConfigSourceRequest) returns (GetConfigSourceResponse);

  // Create a hostname with the URL service.
  rpc CreateHostname(CreateHostnameRequest) returns (CreateHostnameResponse);

  // Delete a hostname with the URL service.
  rpc DeleteHostname(DeleteHostnameRequest) returns (google.protobuf.Empty);

  // List all our registered hostnames.
  rpc ListHostnames(ListHostnamesRequest) returns (ListHostnamesResponse);

  // QueueJob queues a job for execution by a runner. This will return as
  // soon as the job is queued, it will not wait for execution.
  rpc QueueJob(QueueJobRequest) returns (QueueJobResponse);

  // CancelJob cancels a job. If the job is still queued this is a quick
  // and easy operation. If the job is already completed, then this does
  // nothing. If the job is assigned or running, then this will signal
  // the runner about the cancellation but it may take time.
  //
  // This RPC always returns immediately. You must use GetJob or GetJobStream
  // to wait on the status of the cancellation.
  rpc CancelJob(CancelJobRequest) returns (google.protobuf.Empty);

  // GetJob queries a job by ID.
  rpc GetJob(GetJobRequest) returns (Job);

  // ListJobs will return a list of jobs known to Waypoint server. Can be filtered
  // by request on values like workspace, project, application, job state, etc.
  rpc ListJobs(ListJobsRequest) returns (ListJobsResponse);

  // ValidateJob checks if a job appears valid. This will check the job
  // structure itself (i.e. missing fields) and can also check to ensure
  // the job is assignable to a runner.
  rpc ValidateJob(ValidateJobRequest) returns (ValidateJobResponse);

  // GetJobStream opens a job event stream for a running job. This can be
  // used to listen for terminal output and other events of a running job.
  // Multiple listeners can open a job stream.
  rpc GetJobStream(GetJobStreamRequest) returns (stream GetJobStreamResponse);

  // GetRunner gets information about a single runner.
  rpc GetRunner(GetRunnerRequest) returns (Runner) {}

  // ListRunners lists runners that are currently registered with the waypoint server.
  // This list does not include previous on-demand runners that have exited.
  rpc ListRunners(ListRunnersRequest) returns (ListRunnersResponse);

  // AdoptRunners allows marking a runner as adopted or rejected.
  rpc AdoptRunner(AdoptRunnerRequest) returns (google.protobuf.Empty);

  // ForgetRunner deletes an existing runner entry and makes the server
  // behave as if the runner no longer exists. If the runner is currently
  // running, it will receive errors on subsequent jobs, and will have to
  // re-register. A forgotten runner will not be assigned new jobs until
  // re-registered.
  rpc ForgetRunner(ForgetRunnerRequest) returns (google.protobuf.Empty);

  // GetServerConfig sets configuration for the Waypoint server.
  rpc GetServerConfig(google.protobuf.Empty) returns (GetServerConfigResponse);

  // SetServerConfig sets configuration for the Waypoint server.
  rpc SetServerConfig(SetServerConfigRequest) returns (google.protobuf.Empty);

  // CreateSnapshot creates a new database snapshot.
  rpc CreateSnapshot(google.protobuf.Empty) returns (stream CreateSnapshotResponse);

  // RestoreSnapshot performs a database restore with the given snapshot.
  // This API doesn't do a full online restore, it only stages the restore
  // for the next server start to finalize the restore. See the arguments for
  // more information.
  rpc RestoreSnapshot(stream RestoreSnapshotRequest) returns (google.protobuf.Empty);

  // BootstrapToken returns the initial token for the server. This can only
  // be requested once on first startup. After initial request this will
  // always return a PermissionDenied error.
  rpc BootstrapToken(google.protobuf.Empty) returns (NewTokenResponse);

  // DecodeToken takes a token string and returns the structured information
  // about the given token. This is useful for frontends (CLI, UI, etc.) to
  // learn more about a token before using it. For example, if a UI wants to
  // create a signup flow around signup tokens, they can validate the token
  // ahead of time.
  //
  // This endpoint does NOT require authentication.
  rpc DecodeToken(DecodeTokenRequest) returns (DecodeTokenResponse);

  // Generate a new invite token that users can exchange for a login token.
  // This can be used to also invite new users to the Waypoint server.
  rpc GenerateInviteToken(InviteTokenRequest) returns (NewTokenResponse);

  // Generate a new login token that users can use to login directly.
  // This can only be called for existing users.
  rpc GenerateLoginToken(LoginTokenRequest) returns (NewTokenResponse);

  // Generate a new runner token that can be used with runners so they
  // immediately begin work. The recommended appraoch is to instead use
  // the adoption flow but this also works.
  rpc GenerateRunnerToken(GenerateRunnerTokenRequest) returns (NewTokenResponse);

  // Exchange a invite token for a login token. If the invite token is
  // for a new user, this will create a new user account with the provided
  // username hint.
  rpc ConvertInviteToken(ConvertInviteTokenRequest) returns (NewTokenResponse);

  //----------------------------------------------------------------------
  // Runner endpoints. These are expected to be called only by a runner.
  // These are not meant to be public endpoints.
  //----------------------------------------------------------------------

  // RunnerToken is called to register a runner and request a token for
  // remaining runner API calls. This kicks off the "adoption" process
  // (if necessary).
  //
  // This is unauthenticated (but requires a cookie in the metadata).
  rpc RunnerToken(RunnerTokenRequest) returns (RunnerTokenResponse);

  // RunnerConfig is called to receive the configuration for the runner.
  // The response is a stream so that the configuration can be updated later.
  rpc RunnerConfig(stream RunnerConfigRequest) returns (stream RunnerConfigResponse);

  // RunnerJobStream is called by a runner to request a single job for
  // execution and update the status of that job.
  rpc RunnerJobStream(stream RunnerJobStreamRequest) returns (stream RunnerJobStreamResponse);

  // RunnerGetDeploymentConfig is called by a runner for a deployment operation
  // to determine the settings to use for a deployment.
  rpc RunnerGetDeploymentConfig(RunnerGetDeploymentConfigRequest) returns (RunnerGetDeploymentConfigResponse);

  //----------------------------------------------------------------------
  // Entrypoint binary endpoints. These are all expected to be called by
  // the entrypoint binary only.
  //----------------------------------------------------------------------

  // EntrypointConfig is called to get the configuration for the entrypoint
  // and also to get any potential updates.
  //
  // This endpoint also registers the instance with the server. This MUST be
  // called first otherwise other RPCs related to the entrypoint may fail
  // with FailedPrecondition.
  rpc EntrypointConfig(EntrypointConfigRequest) returns (stream EntrypointConfigResponse);

  // EntrypointLogStream is called to open the stream that logs are sent to.
  rpc EntrypointLogStream(stream EntrypointLogBatch) returns (google.protobuf.Empty);

  // EntrypointExecStream is called to open the data stream for the exec session.
  rpc EntrypointExecStream(stream EntrypointExecRequest) returns (stream EntrypointExecResponse);

  //----------------------------------------------------------------------
  // Waypoint.hcl functions. These endpoints don't modify any server state,
  // they're conveniences to build tools on top of Waypoint.
  //----------------------------------------------------------------------

  // WaypointHclFmt formats a waypoint.hcl file. This must be in HCL format.
  // JSON formatting is not supported.
  rpc WaypointHclFmt(WaypointHclFmtRequest) returns (WaypointHclFmtResponse);

  //----------------------------------------------------------------------
  // OnDemand Runner Config functions.
  //----------------------------------------------------------------------

  // UpsertOnDemandRunnerConfig updates or inserts a on-demand runner
  // configuration. This configuration can be used by projects for running
  // operations on just-in-time launched runners.
  rpc UpsertOnDemandRunnerConfig(UpsertOnDemandRunnerConfigRequest) returns (UpsertOnDemandRunnerConfigResponse);

  // GetOnDemandRunnerConfig returns the on-demand runner configuration.
  rpc GetOnDemandRunnerConfig(GetOnDemandRunnerConfigRequest) returns (GetOnDemandRunnerConfigResponse);

  // GetOnDemandRunnerConfig returns the on-demand runner configuration.
  rpc DeleteOnDemandRunnerConfig(DeleteOnDemandRunnerConfigRequest) returns (DeleteOnDemandRunnerConfigResponse);

  // ListOnDemandRunnerConfigs returns a list of all the on-demand runners configs.
  rpc ListOnDemandRunnerConfigs(google.protobuf.Empty) returns (ListOnDemandRunnerConfigsResponse);

  //----------------------------------------------------------------------
  // Internal metadata endpoints. The endpoints below are expected to be
  // called for internal bookkeeping only. They should be avoided for general
  // API clients since they can be used to damage internal state.
  //----------------------------------------------------------------------

  // UpsertBuild updates or inserts a build. A build is responsible for
  // taking some set of source information and turning it into an initial
  // artifact. This artifact is considered "local" until it is pushed.
  rpc UpsertBuild(UpsertBuildRequest) returns (UpsertBuildResponse);

  // UpsertPushedArtifact updates or inserts a pushed artifact. This is
  // useful for local operations to work on a pushed artifact.
  rpc UpsertPushedArtifact(UpsertPushedArtifactRequest) returns (UpsertPushedArtifactResponse);

  // UpsertDeployment updates or inserts a deployment.
  rpc UpsertDeployment(UpsertDeploymentRequest) returns (UpsertDeploymentResponse);

  // UpsertRelease updates or inserts a release.
  rpc UpsertRelease(UpsertReleaseRequest) returns (UpsertReleaseResponse);

  // UpsertStatusReport updates or inserts a statusreport.
  rpc UpsertStatusReport(UpsertStatusReportRequest) returns (UpsertStatusReportResponse);

  //----------------------------------------------------------------------
  // Task functions
  //----------------------------------------------------------------------

  // GetTask returns a requested Task message. Or an error if it does not exist.
  rpc GetTask(GetTaskRequest) returns (GetTaskResponse);

  // ListTask will return a list of all existing Tasks
  rpc ListTask(ListTaskRequest) returns (ListTaskResponse);

  // CancelTask will attempt to gracefully cancel each job in the task job triple
  rpc CancelTask(CancelTaskRequest) returns (google.protobuf.Empty);

  //----------------------------------------------------------------------
  // Trigger URL Config functions
  //----------------------------------------------------------------------

  // UpsertTrigger updates or inserts a trigger URL configuration.
  rpc UpsertTrigger(UpsertTriggerRequest) returns (UpsertTriggerResponse);

  // GetTrigger returns a requested trigger message. Or an error if it does not exist.
  rpc GetTrigger(GetTriggerRequest) returns (GetTriggerResponse);

  // DeleteTrigger takes a trigger id and deletes it, if it exists.
  rpc DeleteTrigger(DeleteTriggerRequest) returns (google.protobuf.Empty);

  // ListTriggers takes a request filter, and returns any matching existing triggers
  rpc ListTriggers(ListTriggerRequest) returns (ListTriggerResponse);

  // RunTrigger will look up the referenced trigger and attempt to queue a job
  // based on the trigger configuration.
  rpc RunTrigger(RunTriggerRequest) returns (RunTriggerResponse);

  //----------------------------------------------------------------------
  // Pipeline endpoints
  //----------------------------------------------------------------------

  // UpsertPipeline updates or inserts a pipeline. This is an INTERNAL ONLY
  // endpoint that is meant to only be called by runners. Calling this manually
  // can risk the internal state for pipelines. In the future, we'll restrict
  // access to this via ACLs.
  rpc UpsertPipeline(UpsertPipelineRequest) returns (UpsertPipelineResponse);

  // RunPipeline queues a pipeline execution.
  rpc RunPipeline(RunPipelineRequest) returns (RunPipelineResponse);

  // GetPipeline returns a pipeline proto by pipeline ref id
  rpc GetPipeline(GetPipelineRequest) returns (GetPipelineResponse);

  // GetPipelineRun returns a pipeline run proto by pipeline ref id and sequence
  rpc GetPipelineRun(GetPipelineRunRequest) returns (GetPipelineRunResponse);

  // ListPipelines takes a project and evaluates the projects config to get
  // a list of Pipeline protos to return in the response. These pipelines
  // are scoped to a single project from the request. It will return an
  // error if the requested project does not exist, or an empty response
  // if no pipelines are defined for the project.
  rpc ListPipelines(ListPipelinesRequest) returns (ListPipelinesResponse);

  // ListPipelineRuns takes a pipeline ref and returns a list of runs of that pipeline.
  // It will return an error if the requested pipeline does not exist, or an empty response
  // if there are no runs for the pipeline.
  rpc ListPipelineRuns(ListPipelineRunsRequest) returns (ListPipelineRunsResponse);

  // ConfigSyncPipeline takes a request for a given project and syncs the current
  // project config to the Waypoint database.
  rpc ConfigSyncPipeline(ConfigSyncPipelineRequest) returns (ConfigSyncPipelineResponse);

  //----------------------------------------------------------------------
  // UI endpoints. The endpoints below are convenience methods for Waypoint's
  // various UIs (web GUI and CLI). They contain no unique functionality, i.e.
  // anything achievable through these endpoints should also be achievable through
  // a combination of calls to non-UI endpoints.
  //----------------------------------------------------------------------

  // Get a given project with useful related records.
  rpc UI_GetProject(UI.GetProjectRequest) returns (UI.GetProjectResponse);

  // List deployments for a given application.
  rpc UI_ListDeployments(UI.ListDeploymentsRequest) returns (UI.ListDeploymentsResponse);

  // List releases for a given application.
  rpc UI_ListReleases(UI.ListReleasesRequest) returns (UI.ListReleasesResponse);
}

/********************************************************************
* UI
********************************************************************/
message UI {
  message GetProjectRequest {
    Ref.Project project = 1;
  }

  message GetProjectResponse {
    Project project = 1;
    Job latest_init_job = 2;
  }


  message ListDeploymentsRequest {
    // Application that the deployments belong to.
    Ref.Application application = 1;

    // Workspace that the deployments belong to.
    // If undefined, deployments from all workspaces will be listed.
    Ref.Workspace workspace = 2;

    OperationOrder order = 3;

    // The filters to apply to this request. These are ORed, so you should
    // specify multiple filters in the StatusFilter for AND behavior.
    repeated StatusFilter status = 4;

    // The physical state to filter for. If this is zero or unset then no
    // filtering on physical state will be done.
    Operation.PhysicalState physical_state = 5;
  }

  message ListDeploymentsResponse {
    // The list of deployments with related messages prefetched.
    repeated UI.DeploymentBundle deployments = 1;
  }

  // A deployment packaged alongside prefetched related messages.
  message DeploymentBundle {
    // The deployment in question.
    Deployment deployment = 1;

    // Populated when a Deployment is read with LoadDetails set
    // to ARTIFACT or BUILD
    PushedArtifact artifact = 3;

    // Populated when a Deployment is read with LoadDetails set to BUILD
    Build build = 4;

    // The deployment-specific URL from the URL service. This is set on
    // all deployment API calls. This will be empty if the URL service
    // is not enabled or there was an error loading this information.
    string deploy_url = 5;

    // The ref that was used in the job to run this operation. This is
    // also accessible by querying the job via the job_id and should always
    // match.
    //
    // This may be null under multiple circumstances: (1) the job was
    // manually triggered with local data (no datasource) or (2) the job
    // was run in earlier versions of Waypoint before we tracked this or
    // (3) the job hasn't yet loaded the data.
    //
    // This is always pre-populated if it is exists.
    Job.DataSource.Ref job_data_source_ref = 6;

    // The most recent status report generated for this deployment.
    StatusReport latest_status_report = 2;
  }

  message ListReleasesRequest {
    // Application that the releases belong to.
    Ref.Application application = 1;

    // Workspace that the releases belong to.
    // If undefined, releases from all workspaces will be listed.
    Ref.Workspace workspace = 2;

    OperationOrder order = 3;

    // The filters to apply to this request. These are ORed, so you should
    // specify multiple filters in the StatusFilter for AND behavior.
    repeated StatusFilter status = 4;

    // The physical state to filter for. If this is zero or unset then no
    // filtering on physical state will be done.
    Operation.PhysicalState physical_state = 5;
  }

  message ListReleasesResponse {
    // The list of releases with related messages prefetched.
    repeated UI.ReleaseBundle releases = 1;
  }

  // A release packaged alongside prefetched related messages.
  message ReleaseBundle {
    // The release in question.
    Release release = 1;

    // The most recent status report generated for this release.
    StatusReport latest_status_report = 2;
  }
}


/********************************************************************
* Server Info
********************************************************************/

message GetVersionInfoResponse {
  VersionInfo info = 1;

  // Represents additional features that the current server supports.
  ServerFeatures server_features = 2;
}

// Represents features that the server supports.
// Useful for ensuring compatibility between clients and servers.
message ServerFeatures {
  repeated feature features = 1;

  enum feature {
    FEATURE_UNSPECIFIED = 0;

    // Advertises that this server is capable of receiving inline keepalive messages
    FEATURE_INLINE_KEEPALIVES = 1;
  }
}

message VersionInfo {
  ProtocolVersion api = 1;
  ProtocolVersion entrypoint = 2;

  // Full version string (semver-syntax). This may be hidden/blank for
  // security purposes so clients should gracefully handle blank values.
  string version = 3;

  message ProtocolVersion {
    uint32 current = 1;
    uint32 minimum = 2;
  }
}

/********************************************************************
* Basic Data Model
********************************************************************/

message Application {
  Ref.Project project = 2;

  string name = 1;

  // Indicates signal to be sent to the applications when its config files
  // change.
  string file_change_signal = 3;
}

// Variable stores a variable's value, and metadata to allow for precedence
// sorting and source-specific error messaging
message Variable {
  string name = 1;

  // value stores one of three simple types (string, number, bool) as their
  // matching protobuf format, or any complex hcl type as a raw string. Values
  // taken from cli -var arguments and env vars are all processed as strings;
  // if a complex type is assigned from one of these sources, it is checked
  // for being assigned a complex type in the variable evaluation stage.
  oneof value {
    string str = 2;
    bool bool = 9;
    int64 num = 10;
    // hcl stores values of any complex type in a raw string format, and
    // converts it to hcl when we evaluate variables. This is used when
    // loading values from a file or from the server/UI.
    string hcl = 3;
  }

  // Source tracks where a value came from for more helpful error messaging.
  // This is optional. If unset, we will give a generic error message.
  oneof source {
    // Cli is set if a variable value is set via a -var flag
    google.protobuf.Empty cli = 4;

    // File is set if a variable value is set via a -var-file flag
    File file = 5;

    // Env is set if a variable value is set in the local
    // environment via a WP_VAR_*
    google.protobuf.Empty env = 6;

    // VCS is set if git polling is enabled and an
    // *.auto.wpvars.hcl/json file is found in the repo
    VCS vcs = 7;

    // Server is set if the variable value comes from the server.
    // When we add support for workspace variables, we can store the workspace
    // id here.
    google.protobuf.Empty server = 8;

    // Dynamic config source plugin
    google.protobuf.Empty dynamic = 11;
  }

  FinalValue final_value = 12;

  bool sensitive = 13;

  message File {
    string fileName = 1;
    HclRange hcl_range = 2;
  }

  message VCS {
    string fileName = 1;
    HclRange hcl_range = 2;
  }

  // Types mapped from https://pkg.go.dev/github.com/hashicorp/hcl/v2#Pos
  message HclPos {
    int32 line = 1;
    int32 column = 2;
    int32 byte = 3;
  }

  message HclRange {
    string filename = 1;
    HclPos start = 2;
    HclPos end = 3;
  }

  message FinalValue {
    // value stores one of three simple types (string, number, bool) as their
    // matching protobuf format, or any complex hcl type as a raw string.
    oneof value {
      // 'sensitive' values are hashed as SHA256 values for
      // the purposes of output and logging
      string sensitive = 1;
      string str = 2;
      bool bool = 3;
      int64 num = 4;
      // hcl stores values of any complex type in a raw string format
      string hcl = 5;
    }

    Source source = 6;
    enum Source {
      // This is the final used value's source
      // that is supplied to the user in outputs.
      UNKNOWN = 0;
      DEFAULT = 1;
      FILE = 2;
      CLI = 3;
      ENV = 4;
      VCS = 5;
      SERVER = 6;
      DYNAMIC = 7;
    }
  }
}

message Project {
  string name = 1;

  // The set of applications that are known about this project. Note that
  // this may not exactly represent the project configuration if a user hasn't
  // run `waypoint init` yet.
  //
  // The applications cannot be modified in any Project APIs. You must
  // use the dedicated Application APIs.
  repeated Application applications = 2;

  // If true, then the `-remote` flag or the `waypoint build project/app`
  // syntax can be used with a remote runner. If this is false, then
  // this is not allowed. This is typically configured using the
  // `runner {}` block in the waypoint config.
  bool remote_enabled = 3;

  // Where data is sourced for remote operations. If this isn't set, then
  // there is no default data source and it will be an error if a job is
  // queued for this project without a data source set. This is usually
  // set using the `runner {}` block in the waypoint config.
  Job.DataSource data_source = 4;

  // Polling settings. Polling will trigger a "waypoint up" whenever a
  // new data is detected on the data source. For now, polling is only done
  // on the `default` workspace. A future version of Waypoint will expand
  // polling to other workspaces.
  //
  // Each polling event is tracked as a separate job. You can query the
  // poll operations and their success/failure by using the ListJobs API.
  Poll data_source_poll = 7;

  // The contents of a default waypoint.hcl file. This will be used ONLY IF
  // this project does not have a waypoint.hcl file when an operation is
  // executed. When this is used, local operations can't be run any more
  // since the CLI usually determines the project based on the waypoint.hcl
  // file. The CLI may still be used for remote operations by executing
  // i.e. waypoint up <project>
  bytes waypoint_hcl = 5;
  Hcl.Format waypoint_hcl_format = 6;

  // Indicates signal to be sent to any applications when their config files
  // change.
  string file_change_signal = 8;

  // Variable values stored on the server. These values are set in the UI.
  repeated Variable variables = 9;

  // Application polling settings. Polling will trigger a "StatusFunc" for collecting a
  // report on the current status of the application.
  // For now, polling is only done on the `default` workspace. A future
  // version of Waypoint will expand polling to other workspaces.
  //
  // Each polling event is tracked as a separate job. You can query the
  // poll operations and their success/failure by using the ListJobs API.
  AppStatusPoll status_report_poll = 10;

  message Poll {
    // enabled must be set to true to enable polling.
    bool enabled = 1;

    // interval is a duration string of how often to poll, such as "5s".
    // The server may enforce minimum values, in which case a value lower
    // than the minimum will be ignored.
    string interval = 2;
  }

  message AppStatusPoll {
    // enabled must be set to true to enable application polling for the project
    bool enabled = 1;

    // interval is a duration string of how often to poll, such as "5s".
    // The server may enforce minimum values, in which case a value lower
    // than the minimum will be ignored.
    string interval = 2;
  }

  ProjectState state = 11;

  // ProjectState is set to active when the project is created and throughout its lifetime.
  // When a project destroy operation begins, the state is set to destroying.
  enum ProjectState {
    ACTIVE = 0;
    DESTROYING = 1;
  }
}

message Workspace {
  // Old fields that were removed.
  reserved 2;
  reserved "applications";

  string name = 1;

  // The list of projects that have executed at least one operation within
  // the context of this workspace.
  repeated Project projects = 4;

  // active_time is the last time that this workspace had activity.
  google.protobuf.Timestamp active_time = 3;

  message Project {
    // Project that this is referencing.
    Ref.Project project = 1;

    // Workspace that this project is part of. This will only be set
    // when using the GetProject API. This will ALWAYS BE NIL on workspace
    // list and get APIs.
    Ref.Workspace workspace = 5;

    // The last non-local ref that was used for any operation.
    Job.DataSource.Ref data_source_ref = 2;

    // active_time is the last time that this project had activity in
    // this workspace.
    google.protobuf.Timestamp active_time = 3;

    // The list of applications that have executed at least one operation
    // within the context of this workspace. To determine which operations
    // you must call the respect list API for that operation, such as
    // ListDeployments.
    repeated Application applications = 4;
  }

  message Application {
    // Application that this is referencing.
    Ref.Application application = 1;

    // active_time is the last time that this application was active
    google.protobuf.Timestamp active_time = 2;
  }
}

// User represents a single user identity within the Waypoint server. A
// user account may represent multiple authentication methods (OIDC from
// multiple sources, tokens, etc.).
message User {
  // Id that is unique to the Waypoint server (usually a ULID).
  string id = 1;

  // username, unique to the Waypoint server. May not be blank,
  // but can be changed. We allow changing so that auth methods
  // such as OIDC can generate non-user-friendly usernames and
  // the user can fix them up later.
  string username = 2;

  // Display name, not used for login. May be blank.
  string display = 3;

  // Email, not used for login. May be blank. May not be verified.
  // Verification currently depends on the auth system. One day maybe
  // Waypoint will handle this.
  string email = 4;

  // Links is the list of account links with 3rd party
  // identity systems.
  repeated Link links = 5;

  // Link is a connection between an authentication provider and
  // the user identity. This is used to lookup a unique user account
  // within Waypoint from multiple auth sources (i.e. GitHub auth,
  // user/pass, etc.).
  message Link {
    oneof method {
      OIDC oidc = 1;
    }

    message OIDC {
      // issuer and sub claims can be used to uniquely identify a user
      string iss = 1;
      string sub = 2;
    }
  }
}

/********************************************************************
* Shared Messages
********************************************************************/

// Ref contains shared messages used for references to other resources.
//
// Refs should be used when the full type shouldn't be embedded in the message.
message Ref {
  // Global references the entire server. This is used in some APIs
  // as a way to read/write values that are server-global.
  message Global {}

  // Application references an application. To uniquely identify an
  // application, this must encapsulate the full hierarchy to the application.
  message Application {
    string application = 1;
    string project = 2;
  }

  // Project references a project.
  message Project {
    string project = 1;
  }

  // Workspace references a workspace.
  message Workspace {
    string workspace = 1;
  }

  message Deployment {
    // Either reference the latest deployment, or a specific deployment id
    oneof ref {
      bool latest = 1;

      uint64 sequence = 2;
    }
  }

  message Artifact {
    // Either reference the latest artifact, or a specific artifact id
    oneof ref {
      bool latest = 1;

      uint64 sequence = 2;
    }
  }

  // Component references a component.
  message Component {
    hashicorp.waypoint.Component.Type type = 1;
    string name = 2;
  }

  // Operation references an operation (build, deploy, etc.). This can reference
  // an operation in multiple ways so you must use the oneof to choose.
  message Operation {
    oneof target {
      string id = 1;
      OperationSeq sequence = 2;
    }
  }

  // OperationSeq references an operation by sequence number.
  message OperationSeq {
    Application application = 1;
    uint64 number = 2;
  }

  // Runner references a runner process which executes operations. This
  // can reference a runner by any of the more specific types, such as
  // by ID. If you want to constrain which runners can be targeted,
  // a different ref type should be used.
  message Runner {
    oneof target {
      RunnerAny any = 1;
      RunnerId id = 2;
      RunnerLabels labels = 3;
    }
  }

  // RunnerAny will reference any runner.
  message RunnerAny {}

  // RunnerId references a runner by ID.
  message RunnerId {
    string id = 1;
  }

  // RunnerLabels references a runner by labels.
  // The labels can be a subset match or an exact match.
  message RunnerLabels {
    map<string, string> labels = 1;
  }

  // User references a user by either ID or username, it is up to the caller.
  // This generic form makes it easy for APIs to accept multiple values, whatever
  // is easiest for the caller.
  message User {
    oneof ref {
      UserId id = 1;
      UserUsername username = 2;
    }
  }

  // UserId references a user by their ID (ULID-formatted).
  message UserId {
    string id = 1;
  }

  // UserUsername references a user by their username. Note that usernames
  // are unique but can be changed at anytime, so for long-living refs
  // the ID should be used.
  message UserUsername {
    string username = 1;
  }

  // AuthMethod references an auth method.
  message AuthMethod {
    string name = 1;
  }

  // DeclaredResource references a declared resource.
  message DeclaredResource {
    string name = 1;
  }

  // OnDemandRunnerConfig references an OnDemandRunnerConfig value to be used for contextual
  // operation. The reference can by via id or name, with id taking priority if both are set.
  message OnDemandRunnerConfig {
    string id = 1;
    string name = 2;
  }

  // Trigger references a Trigger message value to be used for a given operation.
  // It can be looked up by id.
  message Trigger {
    string id = 1;
  }

  // Job references a Job message value by job id.
  message Job {
    string id = 1;
  }

  // Task references a Task message by its id or the main run job id it queued
  message Task {
    oneof ref {
      // the id of the tracktask record
      string id = 1;

      // The main "run" job ID that the task initiated
      string job_id = 2;
    }
  }

  // Pipeline references a pipeline using one or more lookup types.
  message Pipeline {
    oneof ref {
      // Reference a single pipeline by ID.
      string id = 1;

      // Reference an existing pipeline by Project name and Pipeline name
      // Format: "project-name/pipeline-name"
      // This assumes that a project cannot have two pipelines with the same name.
      PipelineOwner owner = 2;
    }
  }

  message PipelineOwner {
    // the project this pipeline is associated with
    Ref.Project project = 1;

    // the name of the defined pipeline config
    string pipeline_name = 2;
  }

  message PipelineStep {
    // ID of the pipeline
    string pipeline_id = 1;

    // Name of the pipeline
    string pipeline_name = 2;

    // Step name within the pipeline.
    string step = 3;

    // Pipeline run sequence
    uint64 run_sequence = 4;
  }
}

// Component represents metadata about a component. A component is the
// generic name for a builder, registry, platform, etc.
message Component {
  // type of the component
  Type type = 1;

  // name of the component
  string name = 2;

  // Supported component types, the values here MUST match the enum values
  // in the Go sdk/component package exactly. A test in internal/server
  // validates this.
  enum Type {
    UNKNOWN = 0;
    BUILDER = 1;
    REGISTRY = 2;
    PLATFORM = 3;
    RELEASEMANAGER = 4;
  }
}

// Status represents the status of an async operation.
message Status {
  // state is the state of this operation.
  State state = 1;

  // details may be non-empty to provide human-friendly information
  // about the current status. This may change between status updates
  // for the same state to provide updated details about the state.
  string details = 2;

  // error is set if the state == ERROR with the error that occurred.
  google.rpc.Status error = 3;

  // start_time is the time the operation was started.
  google.protobuf.Timestamp start_time = 4;

  // complete_time is the time the operation completed (success or fail).
  google.protobuf.Timestamp complete_time = 5;

  enum State {
    UNKNOWN = 0;
    RUNNING = 1;
    SUCCESS = 2;
    ERROR = 3;
  }
}

message StatusFilter {
  // Filters are ANDed together.
  repeated Filter filters = 1;

  message Filter {
    oneof filter {
      // state will match any status that has the given state.
      Status.State state = 2;
    }
  }
}

// Operation is a shared message type used to describe "operations" which are
// executions of a build, deploy, etc. This just contains shared message types
// used for fields. Each individual operation has their own message type
// such as Deployment.
message Operation {
  // PhysicalState is the state of any physical resources associated with
  // an operation. A physical resource for example is the actual container
  // that might be created alongside an operation.
  enum PhysicalState {
    UNKNOWN = 0;
    PENDING = 1;
    CREATED = 3;
    DESTROYED = 4;
  };
}

// OperationOrder is a shared message type used for controlling the order
// of results in queries for app operations such as build, deploys, etc.
message OperationOrder {
  // Order for the results.
  Order order = 2;
  bool desc = 3;

  // Limit the number of results
  uint32 limit = 4;

  enum Order {
    UNSET = 0;
    START_TIME = 1;
    COMPLETE_TIME = 2;
  }
}

// Generation is a shared message type used by operations to denote the
// "generation" they're a part of. A generation denotes whether shared
// physical resources were used or whether new resources were created.
// Another way to conceptualize generations: immutable deployment models
// will create new generations each operation, whereas mutable models will
// reuse a generation.
//
// The concept of a "Generation" was introduced in Waypoint 0.4. Operations
// from earlier versions will have nil generations and callers must handle
// that scenario.
//
// == Read/Write Notes
//
// Callers inserting operations should ONLY set the generation ID. Remaining
// fields will be automatically populated.
//
// Updates should never modify the generation.
message Generation {
  // Id is the unique identifier for this generation. This value is opaque.
  // Waypoint internally only requires that two different generations have
  // two different IDs. The format of the value can be anything.
  string id = 1;

  // This is the sequence number of the first operation that introduced
  // this generation. Once all operations using a sequence number are fully
  // destroyed, a reused generation will introduce a new sequence number.
  //
  // This should not be manually set. This value will be automatically
  // populated on insert. Updates should not modify this value.
  //
  // Consumers can compare this to the sequence number of the operation
  // to determine if this generation is new or existing.
  uint64 initial_sequence = 2;
}

// A platform resource that an operation (release/deployment) has created, depends on, or manages.
message DeclaredResource {
  // platform-specific name of the resource type. i.e. instance, pod, auto-scaling group, etc
  string name = 1;

  // platform-specific type of the resource type. i.e. instance, pod, auto-scaling group, etc
  string type = 6;

  // The platform on which the resource should exist, i.e. docker, gcp, k8s, etc.
  string platform = 2;

  // Internal ResourceManager representation of the resource.
  opaqueany.Any state = 3;

  // Any additional information a plugin wants to expose on this resource.
  // EX: Availability zones on a load balancer, concurrency limit on a lambda function, etc.
  string state_json = 4;

  // high level type of the resource, used for display purposes.
  ResourceCategoryDisplayHint category_display_hint = 5;
}

message DestroyedResource {
  // Unique name name for the resource. Usually derived from the platform. Required.
  string name = 1;

  // platform-specific type of the resource type. i.e. instance, pod, auto-scaling group, etc
  string type = 2;

  // The platform on which the resource should exist, i.e. docker, gcp, k8s, etc.
  string platform = 3;

  // Internal ResourceManager representation of the resource.
  opaqueany.Any state = 4;

  // Any additional information a plugin wants to expose on this resource.
  // EX: Availability zones on a load balancer, concurrency limit on a lambda function, etc.
  string state_json = 5;
}

enum ResourceCategoryDisplayHint {
  UNKNOWN = 0;
  OTHER = 1; // catch-all for types that do not fit well into other predefined roles. i.e. aws target group
  INSTANCE = 2; // i.e. k8s pod, docker container, ecs task
  INSTANCE_MANAGER = 3; // i.e. k8s deployment, ec2 asg, nomad job, ecs service
  ROUTER = 4; // i.e. k8s service, aws alb
  POLICY = 5; // i.e. aws security group or iam role, k8s RoleBinding
  CONFIG = 6; // i.e. aws launch config, k8s configmap
  FUNCTION = 7; // i.e. lambda function, azure function
  STORAGE = 8; // i.e. EBS volume, EFS filesystem, k8s PVC
}

/********************************************************************
* Tasks
********************************************************************/

// TaskLaunchInfo gets stored on the job/operation when queued for execution.
// It details various options required for the task it will launch.
message TaskLaunchInfo {
  // The URL of the OCI image to execute the task under.
  string oci_url = 1;

  // The environment variables that will be exposed to the task.
  map<string, string> environment_variables = 2;

  // Entrypoint is the entrypoint override for the OCI image. If this
  // is not set (null or length of zero) then the entrypoint should not
  // be overridden.
  repeated string entrypoint = 4;

  // The arguments that will be passed to the new container on boot.
  // These are arguments and should not overwrite the entrypoint.
  repeated string arguments = 3;
}

// Task tracks the life of an on-demand runner task that spawns Start
// and Stop tasks for any kind of job/operation in Waypoint. Automatic jobs
// such as project polling or status report generation spawn on-demand
// runner tasks, and this message can be used to track the life of those
// automated jobs. Note that every on-demand runner task is wrapped with a
// Start and Stop task, which we track here as well.
message Task {
  // The ID of this message. If on first upsert, the id does not need to be
  // specified and the state pkg will autogenerate an id. Specifying an id
  // assumes the Task message already exists in the database.
  string id = 1;

  // task_job represents the "run" job the runner will execute, i.e. the operation
  // that was requested to run on the runner.
  // The referred job stores data like ODR config, the target runner used,
  // timestamp for when job started or completed, operation state for task, etc.
  // Currently the only required field when Upserting a Task.
  Ref.Job task_job = 2;

  // watch_job will spawn a job to stream logs from the `task_job`.
  Ref.Job watch_job = 9;

  // Both start_job and stop_job relate to task_job.These jobs were
  // responsible for starting and stopping the runner which executed the task
  // job.
  Ref.Job start_job = 3;
  Ref.Job stop_job = 4;

  // This task info message represented as JSON-encoded protobuf structure of
  // the Any field below. It does not modify any of the structure.
  string state_json = 5;

  // This task info message represented as an Any format. This is the full
  // task encoded directly by the server that has access to the proto to decode it.
  opaqueany.Any state = 6;

  // The overall state of the Task triple. See the enum def for details for
  // each possible Task state. This will be computed for each GetTaskResponse
  // based on the Task job ids received from the database.
  State job_state = 7;

  // The resource that gets created to run the task job for this Task
  // TODO(briancain): This field has not been implemented yet. See
  // "internal/runner/operation_task.go" for more info.
  string resource_name = 8;

  enum State {
    UNKNOWN = 0; // no state defined, the default
    PENDING = 1; // no jobs have been ran yet
    STARTING = 2; // start_job is running
    STARTED = 3; // start_job complete, task is not running yet
    RUNNING = 4; // task is running
    COMPLETED = 5; // task is done
    STOPPING = 6; // stop_job is running
    STOPPED = 7; // every job in Task triple is stopped
    MIXED = 8; // jobs are in an undefined state that don't match our expectation
  }
}

message UpsertTaskRequest {
  // The Task to upsert. If the id in the Task message is empty, then this will
  // be an insert in the db. Otherwise if an id was requested, this will act
  // as an update. If the ID isn't found, it will be an error.
  Task task = 1;
}

message UpsertTaskResponse {
  // The resulting Task that was Upserted.
  Task task = 1;
}

message GetTaskRequest {
  // Can be oneof Task id or by the Run job id.
  Ref.Task ref = 1;
}

message GetTaskResponse {
  // The requested Task
  Task task = 1;

  // The Job triple that the task is associated with. These jobs are the full
  // message for each based on the Ref_Job id found inside Task
  Job task_job = 2;
  Job start_job = 3;
  Job stop_job = 4;
  Job watch_job = 5;
}

message DeleteTaskRequest {
  // The referenced task to delete by task id or Run job id.
  Ref.Task ref = 1;
}

message ListTaskRequest {
  repeated Task.State taskState = 1;

  // TODO(briancain): This currently isn't possible to reference the job
  // operation this way. We either need to create a generic Ref operation
  // that incldues every operation defined in Job, or re-define them all
  // here in the same way the Trigger message does for its reference
  //repeated Job.operation taskOperation = 2;
}

message ListTaskResponse {
  // An array of all available Tasks and their jobs
  repeated GetTaskResponse tasks = 1;
}

message CancelTaskRequest {
  // A reference to the task to cancel
  Ref.Task ref = 1;
}

// ErrorDetail is intended for use in `status`.
message ErrorDetail {
  string key = 1;
  string value = 2;
}

/********************************************************************
* User
********************************************************************/

message GetUserRequest {
  // User to get. If this is not set then the currently logged in
  // user will be requested.
  Ref.User user = 1;
}

message GetUserResponse {
  User user = 1;
}

message ListUsersResponse {
  repeated User users = 1;
}

message UpdateUserRequest {
  // User to update along with the edited fields. Please see the docs
  // on User to determine what can be edited. Fields that aren't editable
  // will be ignored.
  User user = 1;
}

message UpdateUserResponse {
  User user = 1;
}

message DeleteUserRequest {
  Ref.User user = 1;
}

/********************************************************************
* Auth Methods
********************************************************************/

// AuthMethod is a mechanism for authenticating to the Waypoint server.
// An AuthMethod deals with AuthN only: it provides identity and trades
// that for a Waypoint token.
message AuthMethod {
  // unique name for this auth method
  string name = 1;

  // human friendly name for display and description. This has no impact
  // internally and is only helpful for the UI and API. This is optional.
  string display_name = 2;
  string description = 3;

  // A selector to determine whether a user who authenticates using this
  // is allowed to authenticate at all. This runs before authentication
  // completes. This can be used to check group membership and so on.
  // Available variables depend on the auth method used.
  //
  // The syntax of this is this:
  // https://github.com/hashicorp/go-bexpr
  // (better docs to follow)
  string access_selector = 4;

  // The method to configure.
  oneof method {
    // OIDC uses OpenID Connect for auth. OIDC is supported by most
    // major identity providers.
    OIDC oidc = 20;
  }

  message OIDC {
    // client ID and secret provided by OIDC provider.
    string client_id = 1;
    string client_secret = 2;

    // scopes is a list of scopes to request from the provider
    repeated string scopes = 3;

    // List of valid audience values to accept login. This can be
    // used to restrict only certain folks in a shared OIDC domain.
    repeated string auds = 4;

    // List of allowed redirect URIs, since our redirect URIs
    // are somewhat dynamic (UI for web UI, localhost server for
    // CLI, etc.). This protects against attack since this is not
    // generally recommended.
    repeated string allowed_redirect_uris = 5;

    // The signing algorithms supported by the OIDC connect server.
    // If this isn't specified, this will default to RS256 since that
    // should be supported according to the RFC. The string values here
    // should be valid OIDC signing algorithms.
    repeated string signing_algs = 11;

    // Discovery URL endpoint to get other information.
    // Required by OIDC.
    string discovery_url = 6;

    // Optional CA certificate chain to validate the discovery URL.
    // Multiple CA certificates can be specified to support easier
    // rotation.
    repeated string discovery_ca_pem = 7;

    // Mapping claims to keys for usage in selectors such as the
    // "access_selector" on the root auth method.
    //
    // claim mappings are available as "value.<name>" and list
    // mappings are available as "list.<name>".
    map<string, string> claim_mappings = 8;
    map<string, string> list_claim_mappings = 9;
  }
}

// This is used by ListOIDCAuthMethods to return the minimal information
// for an OIDC auth method in an unauthenticated setting.
message OIDCAuthMethod {
  // unique identifier used for this auth method. This may or may
  // not be human friendly; use display_name for human display.
  string name = 1;

  // human friendly name
  string display_name = 2;

  // kind is a well known kind of OIDC provider. This is sniffed by
  // the server heuristically and is only here to assist in the UI.
  Kind kind = 3;

  enum Kind {
    UNKNOWN = 0;
    GITHUB = 1;
    GOOGLE = 2;
  }
}

message UpsertAuthMethodRequest {
  // AuthMethod to upsert. See the message for what fields to set.
  AuthMethod auth_method = 1;
}

message UpsertAuthMethodResponse {
  AuthMethod auth_method = 1;
}

message GetAuthMethodRequest {
  Ref.AuthMethod auth_method = 1;
}

message GetAuthMethodResponse {
  AuthMethod auth_method = 1;
}

message DeleteAuthMethodRequest {
  Ref.AuthMethod auth_method = 1;
}

message ListAuthMethodsResponse {
  repeated AuthMethod auth_methods = 1;
}

message ListOIDCAuthMethodsResponse {
  repeated OIDCAuthMethod auth_methods = 1;
}

message GetOIDCAuthURLRequest {
  // OIDC auth method to use
  Ref.AuthMethod auth_method = 1;

  // The URL that authorization should redirect to.
  string redirect_uri = 2;

  // Nonce is a randomly generated string to prevent replay attacks.
  // It is up to the client to generate this. This must then be passed
  // back to CompleteOIDCAuthRequest.
  string nonce = 3;
}

message GetOIDCAuthURLResponse {
  // The URL to begin authorization. The user should go here.
  string url = 1;
}

message CompleteOIDCAuthRequest {
  Ref.AuthMethod auth_method = 1;

  // This should match the GetOIDCAuthURL RPC. This is not used anymore
  // except for verification.
  string redirect_uri = 2;

  // This should be provided from the parameters given to the redirect URL.
  string state = 3;
  string nonce = 4;
  string code = 5;
}

message CompleteOIDCAuthResponse {
  string token = 1;

  // The user that was authenticated. This is the same as if GetUser
  // was called with the token returned. This is eager returned because
  // it is commonly useful and also readily available as part of auth.
  User user = 2;

  // These are all the claims that were associated with this OIDC
  // authentication. This is used for debugging and operator inspection
  // when setting up an OIDC auth method and aren't meant for general purpose
  // use. These may also contain sensitive data so it shouldn't be stored.
  string id_claims_json = 3;
  string user_claims_json = 4;
}

/********************************************************************
* Queueing
********************************************************************/

message QueueJobRequest {
  // The job to queue. See the Job message documentation for more details
  // on what to set.
  Job job = 1;

  // Set an expiration duration. If the job is not assigned and acked
  // in the given duration then the job will be automatically cancelled.
  string expires_in = 2;
}

message QueueJobResponse {
  // the job ID that was queued. This can be used with other RPC methods
  // to check on the status, cancel, etc.
  string job_id = 1;
}


message CancelJobRequest {
  // The job to cancel
  string job_id = 1;

  // Forcefully attempt to cancel the job
  bool force = 2;
}

message ValidateJobRequest {
  // The job to validate.
  Job job = 1;

  // If true, will NOT validate that the job is assignable.
  bool disable_assign = 2;
}

message ValidateJobResponse {
  // valid will be true if the job structure is valid. If it is invalid
  // validation_error will be set with a reason.
  bool valid = 1;
  google.rpc.Status validation_error = 2;

  // assignable will be true if the job is assignable at this point-in-time.
  // Assignable means that there are runners registered with the server that
  // claim to be able to service this job. Note that this is a point-in-time
  // result so it doesn't guarantee that a job will be serviced when queued.
  // Additionally, assignability doesn't imply anything about queue length,
  // so the job may still be queued for some time.
  //
  // This will always be false if "valid" is false since we don't check
  // assignability of invalid jobs.
  bool assignable = 3;
}

// A Job is a job that executes on a runner and is queued by QueueOperation.
message Job {
  reserved 72 to 99; // future operation range

  // id of the job. This is generated on the server side when queued. If
  // you are queueing a job, this must be empty or unset.
  string id = 1;

  // If this is set, then only one job with this singleton_id may exist
  // at any point in the QUEUED state. If QueueJob is called with this set
  // and an existing job is already queued with a matching singleton_id,
  // that job will be overwritten with this job.
  // This is optional.
  string singleton_id = 8;

  // List of IDs that this job depends on. This job will not be allowed to
  // leave the QUEUED state until jobs with these IDs are successfully
  // completed (SUCESS state). If any dependent jobs enter a terminal state
  // that is not SUCCESS, this job will transition to ERROR.
  //
  // These IDs MUST already be registered jobs. It is an error to depend
  // on a non-existent job.
  repeated string depends_on = 10;

  // List of IDs that are in depends_on that are ignored if they error.
  // Normally, when a dependency fails, this job also fails. If the ID
  // is specified in both depends_on AND here, then the dependency is
  // allowed to fail and this task will still run. This is good for jobs
  // that should run no matter what.
  //
  // All IDs in this value must ALSO be present in "depends_on". This field
  // only specifies which of those values can fail.
  repeated string depends_on_allow_failure = 11;

  // The application to target for the operation. Some operations may allow
  // certain fields of this to be empty, so check with the operation
  // documentation to determine what needs to be set. Generally, project
  // must be set.
  // This is required.
  Ref.Application application = 2;

  // The workspace to perform the operation in.
  // This is required.
  Ref.Workspace workspace = 3;

  // The runner that should execute this job.
  // This is required.
  Ref.Runner target_runner = 4;

  // If target_runner is Any and this is set, the job will be executed
  // on an ODR spawned from this config.
  Ref.OnDemandRunnerConfig ondemand_runner = 112;

  // This is optional and overrides the task that is used by the on-demand
  // runner. This requires ODR to exist since the ODR system is used to
  // launch tasks. If an ODR config is not available, queueing this job will
  // fail.
  //
  // This can be used to run custom runner binaries or custom tasks without
  // a runner.
  TaskOverride ondemand_runner_task = 115;

  message TaskOverride {
    // Launch info for the task. The environment variables will be merged
    // with the defaults. If no OCI URL is specified, the ODR profile
    // settings are used.
    TaskLaunchInfo launch_info = 1;

    // If true, the operation will not be queued. This only works with
    // Noop operations out of safety. This is primarliy for tasks that
    // are NOT runners.
    bool skip_operation = 2;
  }

  // Labels are the labels to set for this operation.
  // This is optional.
  map<string, string> labels = 5;

  // data_source determines where the data to operate on (such as the
  // application source code and Waypoint configuration) comes from.
  // If this is not set then QueueJob will populate this if a default
  // data source is configured for the target project.
  //
  // The overrides will set overrides of configs for the data source. This is
  // data source dependent but this allows for example setting the Git ref
  // without knowing the full data source. Invalid overrides will fail the
  // job.
  // Ergo, this is optional.
  DataSource data_source = 6;
  map<string, string> data_source_overrides = 7;

  // Waypoint.hcl file contents. This is OPTIONAL and not typically supplied.
  // If this is not provided, the job will source the waypoint.hcl file
  // from the server or the data source. This can be used to override those
  // and force a specific waypoint.hcl to be used.
  Hcl waypoint_hcl = 12;

  // variables store the key/value pairs of parsed variables; the parse
  // prior to running a job only verifies syntax correctness. Verifying type
  // checks and the presence of required values will both need to be done
  // in the job's validation
  repeated Variable variables = 9;

  // The operation to execute. See the message docs for details on the operation.
  // This is required, set one (and one only).
  oneof operation {
    Noop noop = 50;
    BuildOp build = 51;
    PushOp push = 52;
    DeployOp deploy = 53;
    DestroyOp destroy = 54;
    ReleaseOp release = 55;
    ValidateOp validate = 56;
    AuthOp auth = 57;
    DocsOp docs = 58;
    ConfigSyncOp config_sync = 59;
    ExecOp exec = 60;
    UpOp up = 61;
    LogsOp logs = 62;
    QueueProjectOp queue_project = 63;
    PollOp poll = 64;
    StatusReportOp status_report = 65;
    StartTaskLaunchOp start_task = 66;
    StopTaskLaunchOp stop_task = 67;
    InitOp init = 68;
    WatchTaskOp watch_task = 69;
    PipelineStepOp pipeline_step = 70;
    DestroyProjectOp destroy_project = 71;
  }

  //-----------------------------------------------------------------
  // Server-side fields - the fields below are all set by the server
  // and should not be set on the queueing request.
  //-----------------------------------------------------------------

  // state of the job
  State state = 100;

  // The runner that was assigned to execute this job. Note that the
  // runner may have been ephemeral and may no longer exist.
  Ref.RunnerId assigned_runner = 101;

  // The time when the job was queued.
  google.protobuf.Timestamp queue_time = 102;
  google.protobuf.Timestamp assign_time = 103;
  google.protobuf.Timestamp ack_time = 104;
  google.protobuf.Timestamp complete_time = 105;

  // Ref of the data was fetched for this job. This is available after
  // the Ref event is sent down by GetJobStream. This is NOT used to specify
  // the ref that should be downloaded. That level of configuration should be
  // exposed via the data_source parameter itself.
  DataSource.Ref data_source_ref = 110;

  // Variable refs store the final value used on the operation for each variable
  // defined in the waypoint.hcl. Any variables with `sensitive` set in the
  // waypoint.hcl will have a value hashed with SHA256 so the user can verify
  // the value used.
  map<string, Variable.FinalValue> variable_final_values = 113;

  // Config is information about the Waypoint configuration (waypoint.hcl)
  // for this job. This is only available once the configuration is loaded.
  // If this is nil and the job is RUNNING, then it may not be loaded yet.
  // API users can wait on the Job event on the JobStream to listen for
  // job updates.
  Config config = 111;

  // error is set if state == ERROR
  google.rpc.Status error = 106;

  // result is set based on the operation specified. A nil result is possible
  // for some operations.
  Result result = 107;

  // cancel time is the time that cancellation of this job was requested.
  // If this is zero then this job was not cancelled. Note that this is the
  // cancellation _request_ time. The actual time a job ended is noted by
  // the complete_time field.
  google.protobuf.Timestamp cancel_time = 108;

  // expire time is the time when this job would expire. If this isn't set
  // then this is a non-expiring job. This will remain set even if the job
  // never expired because it was accepted and run. This field can be used
  // to detect that it was configured to expire.
  google.protobuf.Timestamp expire_time = 109;

  // task is a reference to a given Task that this job might be apart of. If
  // the task is Nil, it means the server does not associate this job with
  // an on-demand runner task. If the Task Ref is set, that means this job
  // is part of the referenced task id.
  Ref.Task task = 114;

  // PipelineStep is a reference to the pipeline and step that might have triggered this job.
  // If the PipelineStep is nil, this job was not initiated by a pipeline.
  // If the Pipeline Ref is set, this job is part of the referenced pipeline.
  Ref.PipelineStep pipeline = 117;

  enum State {
    UNKNOWN = 0;
    QUEUED = 1; // queued and waiting for assignment
    WAITING = 2; // assigned to a runner, waiting for runner to ack
    RUNNING = 3; // runner acked and is executing
    ERROR = 4; // job failed
    SUCCESS = 5; // job succeeded
  }

  message Result {
    BuildResult build = 1;
    PushResult push = 2;
    DeployResult deploy = 3;
    ReleaseResult release = 4;
    ValidateResult validate = 5;
    AuthResult auth = 6;
    DocsResult docs = 7;
    ConfigSyncResult config_sync = 8;
    UpResult up = 9;
    QueueProjectResult queue_project = 10;
    PollResult poll = 11;
    StatusReportResult status_report = 12;
    StartTaskResult start_task = 13;
    InitResult init = 14;
    WatchTaskResult watch_task = 15;
    PipelineStepResult pipeline_step = 16;
    PipelineConfigSyncResult pipeline_config_sync = 17;
    ProjectDestroyResult project_destroy = 18;
  }

  message Config {
    // Source is the location where the configuration was loaded from.
    Source source = 1;

    // Source is the location where the configuration was loaded from.
    enum Source {
      // Unknown should never be set, but represents a zero value.
      UNKNOWN = 0;

      // File is when the waypoint.hcl was loaded from a file either
      // on disk (local actions) or the attached repository (GitOps).
      FILE = 1;

      // Server is when the waypoint.hcl was loaded from the server
      // from being written directly in the project settings.
      SERVER = 2;

      // Job is when the waypoint.hcl was loaded directly from the job by
      // being embedded in the "waypoint_hcl" field (tag 12).
      JOB = 3;
    }
  }

  message DataSource {
    oneof source {
      // local means the runner has access to the data locally and will
      // know what to do. This is primarily only useful if the target_runner
      // is a specific runner and should not be used by any runner unless your
      // runners are configured to have access to the proper data.
      Local local = 1;

      // git will check out the data from a Git repository.
      Git git = 2;

      // remote means that the Waypoint server has special logic for how to
      // fetch the data.
      Remote remote = 3;
    }

    // Ref is a reference to the exact set of data used by a data source.
    message Ref {
      oneof ref {
        // unknown is set if the ref is not known or not supported, such
        // as for local data sources where we have no way to uniquely identify.
        google.protobuf.Empty unknown = 1;

        // git commit
        Git.Ref git = 2;
      }
    }
  }

  message Local {}

  message Remote {
    // Description is information about how the Waypoint server
    // acquires the data.
    string description = 1;
  }

  message Git {
    // url of the repository to clone. Local paths are not allowed.
    string url = 1;

    // a ref to checkout. If this isn't specified, then the default
    // ref that is cloned from the URL above will be used.
    string ref = 2;

    // path is a subdirectory within the checked out repository to
    // go into for the project's configuration. This must be a relative path
    // and may not contain ".."
    string path = 3;

    // This setting only takes effect if both "path" is true AND the
    // Git polling is enabled. Under those conditions, if this option
    // is true, then only changes in Git commits within the "path" will
    // trigger a deploy. Changes outside the "path" will be ignored.
    bool ignore_changes_outside_path = 10;

    // The max depth for recursively cloning submodules. 0 disables submodule
    // cloning.
    uint32 recurse_submodules = 11;

    // auth is the auth mechanism to use for this data source. This is optional.
    // If this isn't set, then the data source will attempt to clone
    // without setting any explicit auth. This usually picks up machine
    // settings like ssh config files and so on if they exist.
    //
    // Note that any auth settings set here are stored in the server and
    // may NOT be encrypted. If you want increased security, we recommend
    // using auth baked into the machine running Waypoint.
    oneof auth {
      Basic basic = 4;
      SSH ssh = 5;
    }

    // Basic auth
    message Basic {
      // username for authentication. If using access token based auth
      // for something like GitHub, this can be any non-empty string.
      string username = 1;

      // password for authentication. If using access token based auth
      // for GitHub, this should be the access token.
      string password = 2;
    }

    // SSH private key auth
    message SSH {
      // private_key_pem is a PEM-encoded private key.
      bytes private_key_pem = 1;

      // password is an optional password for decoding the private key.
      string password = 2;

      // user is the SSH user to use when cloning. This will default to
      // "git" if not specified.
      string user = 3;
    }

    // Ref is used to populate DataSource.Ref
    message Ref {
      // commit is the full commit hash
      string commit = 1;

      // timestamp is the timestamp of the commit
      google.protobuf.Timestamp timestamp = 2;

      // commit_message is the commit message, contains arbitrary text
      string commit_message = 3;
    }
  }

  // Noop operations do nothing. This is primarily used for testing.
  // This operation will still download the data from the data source.
  // A noop may be useful outside of testing to verify a runner is
  // executing properly or can access data properly.
  message Noop {}

  // UpOp runs the "waypoint up" logic: it does a build (with push),
  // deploy, and release all in one. The results for each child operation
  // will be set directly on the Release message (i.e. "build" will be
  // populated in addition to "up").
  message UpOp {
    // Options for the release stage. The "deployment" field in this will
    // be ignored since we'll always use the deployment from the deploy
    // step in Up.
    ReleaseOp release = 1;
  }

  // UpResult is the result of an UpOp. Because "up" calls other operations,
  // the Result message will set the build, deploy, push, and release results.
  message UpResult {
    // release_url is the equivalent of Release.Url. This is the URL that
    // the release plugin generates directly from the platform. For example,
    // on AWS this might be an ALB addr, on K8S this might be a load balancer
    // addr, etc.
    //
    // This can be empty if the release plugin does not support getting a URL.
    string release_url = 1;

    // app_url is the HashiCorp URL service URL for the entire application.
    // Example: mistakenly-crucial-malamute.waypoint.run. If there are multiple
    // hostnames registered for the application, this always picks the first one.
    //
    // This can be blank if the URL service is disabled or errored.
    string app_url = 2;

    // deploy_url is the HashiCorp URL service URL for this specific deploy.
    // Example: mistakenly-crucial-malamute--v1.waypoint.run. Similar to app_url,
    // if there are multiple registered hostnames for the application, this
    // always picks the first one.
    //
    // This can be blank if the URL service is disabled or errored.
    string deploy_url = 3;
  }

  // ValidateOp validates various aspects of a configuration.
  message ValidateOp {}

  message ValidateResult {}

  // AuthOp is the configuration to authenticate any plugins.
  message AuthOp {
    // if true, auth will only be checked but not attempted. Currently
    // this must ALWAYS be true. Only authentication checking is supported.
    bool check_only = 1;

    // if set, only the component matching this reference will be authed.
    // If this component doesn't exist, an error will be returned. If this is
    // unset, all components wll be authed.
    Ref.Component component = 2;
  }

  message AuthResult {
    // results are the list of components that were checked
    repeated Result results = 1;

    message Result {
      // component that was checked
      Component component = 1;

      // result of the auth check. If the component didn't implement the
      // auth interface this will be set to true. You can check for interface
      // implementation using auth_supported. If auth is attempted, the auth
      // operation will recheck the status and this value will reflect the
      // check post-auth attempt. You can use this to verify if the auth
      // succeeded.
      bool check_result = 2;
      google.rpc.Status check_error = 3;

      // this is true if the component was authenticated using the Auth
      // callback. If false, then no attempt was made to authenticate. This
      // can be on purpose for example if "check_only" is set to true on
      // the op.
      bool auth_completed = 4;
      google.rpc.Status auth_error = 5;

      // auth supported is true if this component implemented the auth
      // interface.
      bool auth_supported = 6;
    }
  }

  message BuildOp {
    // Don't push the build to any configured registry.
    bool disable_push = 1;
  }

  message BuildResult {
    // The resulting build
    Build build = 1;

    // The artifact that was pushed. This will be nil if DisablePush was set.
    PushedArtifact push = 2;
  }

  message PushOp {
    // Build to push
    Build build = 1;
  }

  message PushResult {
    PushedArtifact artifact = 1;
  }

  message DeployOp {
    // Artifact to deploy
    PushedArtifact artifact = 1;
  }

  message DeployResult {
    Deployment deployment = 1;
  }

  // Used to start a platform's exec function within a runner. This is only used
  // there are no long running instances for a deployment and can fail if the
  // platform plugin does not provide an exec function.
  message ExecOp {
    // Id to assign the virtual instance created
    string instance_id = 1;

    // The deployment to create the exec session context. Ie, what
    // application code will be available within the exec session.
    Deployment deployment = 2;
  }

  message ExecResult {}

  // Used to start a platform's log function within a runner. API users
  // interested in viewing logs should use the GetLogStream API. This
  // is only meant for implementing custom log handling by plugins.
  message LogsOp {
    // Id to assign the virtual instance created
    string instance_id = 1;

    // The deployment to create the exec session context. Ie, what
    // application code will be available within the exec session.
    Deployment deployment = 2;

    // Indicates the time horizon that log entries must be beyond for them
    // to be emitted.
    google.protobuf.Timestamp start_time = 3;

    // The maximum of log entries to be output.
    int32 limit = 4;
  }

  message DestroyOp {
    // target is what to destroy in this operation.
    oneof target {
      // workspace will delete the app in the workspace that the job
      // is targeting.
      google.protobuf.Empty workspace = 1;

      Deployment deployment = 2;
    }
  }

  message ReleaseOp {
    Deployment deployment = 1;

    // Prune settings. This will prune the deployments that aren't released.
    bool prune = 2;

    // This sets the number of unreleased deployments to retain when pruning.
    // This only has an effect if "prune_retain_override" is true. If that
    // is false, then pruning uses the default behavior (retain 2).
    int32 prune_retain = 3;
    bool prune_retain_override = 4;
  }

  message ReleaseResult {
    // The release that was just created. If the release operation was a noop,
    // for example if the target deployment shares a generation with the
    // previously released deployment, then this may be an existing release.
    // Callers can verify by checking if the target deployment changed
    // or not.
    Release release = 1;
  }

  // TaskPluginParams contains the information about a specific task plugin
  // that is used by both StartTask and StopTask
  message TaskPluginParams {
    // The plugin type to invoke for the task plugin.
    string plugin_type = 2;

    // The configuration information for the task. This is HCL that is
    // decoded to figure out the task plugin and then provide that
    // task plugin with configuration
    bytes hcl_config = 3;
    Hcl.Format hcl_format = 4;
  }

  message StartTaskLaunchOp {
    // The info to use to create the task
    TaskLaunchInfo info = 1;

    // Params is needed to spawn the plugin so we can send it the start.
    TaskPluginParams params = 2;
  }

  message StartTaskResult {
    // The state of the create task, used to identify it later.
    opaqueany.Any state = 1;
  }

  message StopTaskLaunchOp {
    // Params is needed to spawn the plugin so we can send it the stop.
    TaskPluginParams params = 2;

    // The state of the start task. This can come in multiple ways.
    oneof state {
      // The state can be directly provided.
      opaqueany.Any direct = 1;

      // The state can be looked up from the result of a StartTask job.
      string start_job_id = 3;
    }
  }

  message WatchTaskOp {
    // The job that started the task (should match up to a StartTaskLaunchOp).
    // This is used to lookup the state to pass to the task.
    Ref.Job start_job = 1;
  }

  message WatchTaskResult {
    int32 exit_code = 1;
  }

  message StatusReportOp {
    oneof target {

      // The deployment that should be associated with this status report
      // operation
      Deployment deployment = 1;

      // The release that should be associated with this status report
      // operation
      Release release = 2;
    }
  }

  message StatusReportResult {
    // The status report that was just created
    StatusReport status_report = 1;
  }

  message DocsOp {}

  message DocsResult {
    // results are the list of components that were checked
    repeated Result results = 1;

    message Result {
      // component that the docs are for
      Component component = 1;
      Documentation docs = 2;
    }
  }

  message ConfigSyncOp {}

  message ConfigSyncResult {}

  message PipelineConfigSyncResult {
    // synced_pipelines is a map of Pipeline Name Keys to Pipeline ID Refs for
    // each pipeline that was synced in the config sync request.
    map<string, Ref.Pipeline> synced_pipelines = 1;
  }

  message ProjectDestroyResult {
    string job_id = 1;
  }

  // PollOp triggers a poll action for a project. The job will fail if there
  // is no data source configured for the project.
  //
  // A poll operation can be queued even if a project has polling disabled.
  // If a project has polling enabled, a manually queued poll operation will
  // have no effect on the poll timer or intervals.
  message PollOp {
    // NOTE(mitchellh): In the future I think we could have options here
    // to poll only specific workspaces or the full project or whatever.
    // At the time of writing this, we only support single workspace anyways.
  }

  message PollResult {
    // This field will be non-empty if and only if polling resulted in
    // new data that needs to be deployed. This will be the ID of the job
    // that queues the "up" operation.
    string job_id = 1;

    // If the poll resulted in new data, old_ref and new_ref will contain
    // the two refs that were currently in use. These are nil if the polling
    // didn't find new data.
    Job.DataSource.Ref old_ref = 2;
    Job.DataSource.Ref new_ref = 3;
  }

  // InitOp triggers an init action for a project (the equivalent of `waypoint
  // init`). The job will fail if there is no data source configured for the
  // project. As with `waypoint init`, this operation is idempotent.
  message InitOp {
  }

  message InitResult {
    // NOTE(jgwhite): In the future I think we may want to communicate what
    // entities were created during the init operation. At the time of writing,
    // there is no pressing reason to add this data.
  }

  // PipelineStepOp triggers the execution of a pipeline step.
  message PipelineStepOp {
    // The step to execute.
    Pipeline.Step step = 1;
  }

  // DestroyProjectOp triggers the deletion of a project from the database
  // as well as (optionally) the destruction of all resources created within
  // a project
  message DestroyProjectOp {
    Ref.Project project = 1;
    bool skip_destroy_resources = 2;
  }

  // Note that since we run pipeline steps as jobs, the output of the pipeline
  // execution is in the job log.
  message PipelineStepResult {
    // The resulting status from the pipeline step execution. This will
    // always be non-nil. On success the code will be OK.
    google.rpc.Status result = 1;
  }

  // QueueProjectOp queues a job for all applications in a project. The
  // applications queued may not directly align with what can be found in
  // ListProjects because the application list will be based on the config
  // and not the database.
  message QueueProjectOp {
    // The template for the job to queue for each application. The "application"
    // field will be overwritten for each application. All other fields are
    // untouched.
    Job job_template = 1;
  }

  message QueueProjectResult {
    // All applications that had jobs queued. This may be empty even if the
    // job was a success. If this is empty, it means that no applications were
    // found to have jobs queued.
    repeated Application applications = 1;

    message Application {
      // Application that was queued.
      Ref.Application application = 1;

      // ID of the job that was queued.
      string job_id = 2;
    }
  }
}

message Documentation {
  string description = 1;
  string example = 2;
  string input = 3;
  string output = 4;
  map<string, Field> fields = 5;
  repeated Mapper mappers = 6;

  message Field {
    string name = 1;
    string synopsis = 2;
    string summary = 3;
    bool optional = 4;
    string env_var = 5;
    string type = 6;
    string default = 7;
  }

  message Mapper {
    string input = 1;
    string output = 2;
    string description = 3;
  }
}


message GetJobRequest {
  // ID of the job to request.
  string job_id = 1;
}

message ListJobsRequest {
  Ref.Workspace workspace = 1;
  Ref.Project project = 2;
  Ref.Application application = 3;
  Ref.Runner targetRunner = 4;
  Ref.PipelineStep pipeline = 5;
  repeated Job.State jobState = 6;
}

message ListJobsResponse {
  repeated Job jobs = 1;
}

message GetJobStreamRequest {
  string job_id = 1;

  // Future: can add a timestamp here so that only output from after the
  // given timestamp is sent down.
}

message GetJobStreamResponse {
  oneof event {
    // Open is sent as confirmation that the job stream successfully opened.
    // This will be sent immediately by the server if the job ID is valid.
    // This is useful since other events such as terminal output may not
    // happen for a long time while the job is executing, queued, etc.
    //
    // This is ALWAYS sent. If the job is already completed, this will be
    // sent first followed immediately by a Complete.
    Open open = 1;

    // state is sent when there is a job state change event. This event is
    // also used if there is job metadata changes. In this case, the state
    // may be the same but the job is different.
    State state = 2;

    // Job is sent whenever the job information changes. This is similar to
    // state but is sent when ANY field in the Job structure changes. This
    // can be used to listen for any updates to fields.
    //
    // The updated job is also sent when the state changes. In that case,
    // both "state" and "job" will trigger.
    JobChange job = 7;

    // terminal output. On initial connection, the server may send buffered
    // historical terminal data so there isn't a race between queueing a job
    // and getting its first byte output. You can determine this based on the
    // flag on Terminal.
    Terminal terminal = 3;

    // data downloaded for the job. This is sent after the state is RUNNING
    // when the runner has cloned any data (if necessary) containing information
    // about the data. This is an optional event and may not be sent, indicating
    // that the runner is either older and doesn't support this event or that
    // there was no data download necessary and it is using local data.
    Download download = 6;

    // an error regarding the stream itself, rather than the executing job.
    // For example, if you request a job stream for an invalid job ID,
    // this will be sent back. If this is sent, no further messages will
    // be sent and the stream is terminated.
    //
    // For errors in job execution, see "complete".
    Error error = 4;

    // job completion, no more events will follow this one. This can be
    // both success or failure, the event must be checked. Any errors
    // in complete are errors from the job execution itself.
    Complete complete = 5;
  }

  message Open {}

  message State {
    // previous and current are the previous and current states, respectively.
    Job.State previous = 1;
    Job.State current = 2;

    // The full updated job is also sent because additional fields may be
    // set depending on the state (such as the assigned runner, assignment
    // times, etc.)
    Job job = 3;

    // canceling is true if the job was requested to be canceled.
    bool canceling = 4;
  }

  message JobChange {
    // The full updated job.
    Job job = 1;
  }

  message Download {
    // The ref for the data that was downloaded. This can be nil if no
    // data was downloaded (though it'd be more reasonable to just not
    // send a download event in that case).
    Job.DataSource.Ref data_source_ref = 1;
  }

  message Terminal {
    repeated Event events = 1;

    // buffered if true signifies that the data being sent is from the
    // server buffer and is historical vs real-time since the stream was
    // opened. If this is true, all lines are buffered. We will never mix
    // buffered and non-buffered lines.
    bool buffered = 2;

    message Event {
      // timestamp of the event as seen by the runner. This might be
      // skewed from the server or the client but relative to all other
      // line output, it will be accurate.
      google.protobuf.Timestamp timestamp = 1;

      oneof event {
        Line line = 2;
        Status status = 3;
        NamedValues named_values = 4;
        Raw raw = 5;
        Table table = 6;
        StepGroup step_group = 7;
        Step step = 8;
      }

      message Status {
        string status = 1;
        string msg = 2;
        bool step = 3;
      }

      message Line {
        string msg = 1;
        string style = 2;
      }

      message Raw {
        bytes data = 1;
        bool stderr = 2;
      }

      message NamedValue {
        string name = 1;
        string value = 2;
      }

      message NamedValues {
        repeated NamedValue values = 1;
      }

      message TableEntry {
        string value = 1;
        string color = 2;
      }

      message TableRow {
        repeated TableEntry entries = 1;
      }

      message Table {
        repeated string headers = 1;
        repeated TableRow rows = 2;
      }

      message StepGroup {
        bool close = 1;
      }

      message Step {
        int32 id = 1;
        bool close = 2;
        string msg = 3;
        string status = 4;
        bytes output = 5;
      }
    }
  }

  message Error {
    google.rpc.Status error = 1;
  }

  message Complete {
    // error, if set, is an error that occurred as part of the job execution
    // and resulted in job termination. This is different than the "error"
    // event which is an error in the stream itself.
    google.rpc.Status error = 1;

    // Result will be set to the final result of the job execution, if any.
    Job.Result result = 2;
  }
}

/********************************************************************
* Runner
********************************************************************/

message Runner {
  // id is a unique ID generated by the runner. This should be a UUID or some
  // other guaranteed unique mechanism. This is not an auth mechanism, just
  // a way to associate an ID to a runner.
  string id = 1;

  // The runner will only be assigned jobs that directly target this
  // runner by ID. This is used by local runners to prevent external
  // jobs from being assigned to them.
  bool by_id_only = 2;

  // Kind indicates what variety of runner this is
  oneof kind {
    // odr is set if this runner as an on-demand runner. For ODRs, we expect
    // they will accept exactly one job and then exit. This is used by the
    // server to change some other behavior:
    //
    //   * The server will give ODRs project/app-scoped config if it exists.
    //   * The server will never assign more than one job to this runner.
    //     This is also enforced in the runner client-side but the server also
    //     does this out of caution.
    //
    ODR odr = 5;

    // local indicates this runner was created by a cli instantiation
    Local local = 6;

    // remote indicates this is a "static" remote runner
    Remote remote = 7;

    // deprecated_is_odr used to be how a runner indicated if it was an ODR type runner.
    // Superseded by the ODR kind (field 5)
    bool deprecated_is_odr = 4;
  }

  // Components are the list of components that the runner supports. This
  // is used to match jobs to this runner.
  repeated Component components = 3;

  // Labels for the runner. These are the same as labels for any other
  // system in Waypoint (see operations such as Deployment). For runners, they
  // can additionally be used as a targeting mechanism.
  map<string, string> labels = 12;

  //----------------------------------------------------------------------
  // Server set fields. The fields below are set by the server and are
  // ignored as part of RunnerConfig.
  //----------------------------------------------------------------------

  // True if this runner is currently online and connected.
  bool online = 11;

  // The timestamps store the time this runner was first seen and the time
  // the runner was last seen. These values can be the same if the runner
  // was seen exactly once. The values are updated only when a runner starts
  // up.
  google.protobuf.Timestamp first_seen = 9;
  google.protobuf.Timestamp last_seen = 10;

  // The state of whether this runner is adopted or not.
  AdoptionState adoption_state = 8;

  // Valid adoption states. The transitions allowed are:
  //
  // - ∅ => NEW
  // - ∅ => PREADOPTED
  // - NEW => PREADOPTED
  // - * => ADOPTED
  // - * => REJECTED
  // - ADOPTED => NEW
  // - REJECTED => NEW
  //
  // Both the "NEW" and "REJECTED" state are effectively "unadopted" states,
  // but they're explicit about why they're not currently adopted. Both
  // "ADOPTED" and "PREADOPTED" are adopted states where the runner will
  // be given work, but are also explicit about how they were adopted.
  enum AdoptionState {
    // New runner we've never seen before or has been forgotten.
    // Runners in this state are pending adoption.
    PENDING = 0;

    // Runner provided a valid runner token despite not being explicitly
    // adopted. This type of runner can be forcibly rejected later such
    // that pre-adoption doesn't work at all.
    PREADOPTED = 1;

    // Explicitly adopted. Runner will get a token on handshake.
    ADOPTED = 2;

    // Explicitly rejected. Runner will error immediately on startup.
    REJECTED = 3;
  };

  message ODR {
    string profile_id = 1;
  }

  message Local {}

  message Remote {}
}

message RunnerTokenRequest {
  // Runner to register. See Runner for what fields can be set.
  Runner runner = 1;
}

message RunnerTokenResponse {
  // The token to use for subsequent API calls. The runner should reconnect
  // and use this token which contains specific adoption information to allow
  // runner APIs through.
  //
  // If this token is empty, that means the token sent for the API request
  // is already valid and no reconnect is necessary; just keep using the same
  // token.
  string token = 1;
}

message RunnerConfigRequest {
  oneof event {
    Open open = 1;
  }

  message Open {
    // Runner to register. See Runner for what fields can be set. This
    // should match RunnerTokenRequest. This accepts a full runner (rather
    // than just an ID) for legacy compatbility reasons.
    Runner runner = 1;
  }
}

message RunnerConfigResponse {
  // config is any updated configuration for the runner.
  RunnerConfig config = 2;
}

message RunnerConfig {
  // The configuration for the runner. Any locally set runner config will
  // take priority in a conflict. This allows operators to setup runners
  // with specific configuration without fear that the server will override
  // them.
  repeated ConfigVar config_vars = 1;

  // The configuration for any config sources that may be used in the
  // config vars sent down. The server may send down extra configs that
  // aren't used so consumers should filter these based on what env vars
  // are actually in use.
  repeated ConfigSource config_sources = 2;
}

message RunnerJobStreamRequest {
  oneof event {
    // request MUST BE the first message sent by a client. This is used to
    // signify that a runner is ready to accept a job. This is only ever
    // sent once. Once a job is complete, the client must terminate the
    // stream and open a new connection.
    Request request = 1;

    // ack is sent to accept a job assignment from the server. This
    // should be sent soon after the job is assigned to avoid the job being
    // reassigned and duplicated.
    //
    // In the reattach use case, this should still be sent to the
    // server in response to job assignment.
    Ack ack = 2;

    // complete is sent on job completion. This is only sent if there
    // were no errors, so this signals a successful completion. An erroneous
    // completion is signaled by sending an Error event.
    Complete complete = 3;

    // error is sent when there was an error with job execution (after
    // accept was sent). This signals that the job failed and it cannot
    // be retried. This terminates the job and no other events should be
    // sent.
    Error error = 4;

    // terminal output from the job.
    GetJobStreamResponse.Terminal terminal = 5;

    // download event is sent after the data is downloaded. This is optional.
    // If this isn't sent the job will still remain in the "running" state but
    // download details will not be available.
    GetJobStreamResponse.Download download = 7;

    // The config_load event is sent after the Waypoint configuration
    // (waypoint.hcl) is loaded. This includes information about the loaded
    // configuration that the frontends can use.
    //
    // This can be sent multiple times to update the configuration information
    // for a job.
    ConfigLoad config_load = 8;

    // update variables
    VariableValuesSet variable_values_set = 9;

    // heartbeat that the job is still running.
    Heartbeat heartbeat = 6;
  }

  message Request {
    // The ID of the runner opening the job stream. This ID must match
    // the ID of the runner token in use.
    string runner_id = 1;

    // If the runner is reconnecting to a dropped connection, it can specify
    // the job ID it is continuing. This can only be specified when the runner
    // is reconnecting to a dropped connection due to network issues or
    // the server process disappearing. This can't currently be safely used
    // for reconnecting after a runner crash, because that case hasn't been
    // thought of yet.
    string reattach_job_id = 2;
  }

  message Ack {}

  message Complete {
    Job.Result result = 1;
  }

  message Error {
    google.rpc.Status error = 1;
  }

  message Heartbeat {}

  message ConfigLoad {
    // Config is the configuration information for the loaded config.
    Job.Config config = 1;
  }

  message VariableValuesSet {
    map<string, Variable.FinalValue> final_values = 1;
  }
}

message RunnerJobStreamResponse {
  oneof event {
    // assignment is when a job is assigned to this job stream. This
    // will happen ONLY in response to a "Request" message from the client.
    //
    // This is sent down for the reattach use case (if reattach is set
    // in Request), too, and the client is expected to Ack it. This
    // verifies that both sides are ready to continue with the job.
    JobAssignment assignment = 1;

    // cancel is sent when a cancel request is made.
    JobCancel cancel = 2;
  }

  message JobAssignment {
    // The job to assign
    Job job = 1;

    // A list of plugin configs
    repeated ConfigSource config_sources = 2;
  }

  message JobCancel {
    bool force = 1;
  }
}

message RunnerGetDeploymentConfigRequest {}

message RunnerGetDeploymentConfigResponse {
  string server_addr = 1;
  bool server_tls = 2;
  bool server_tls_skip_verify = 3;
}

message GetRunnerRequest {
  // ID of the runner to request.
  string runner_id = 1;
}

message ListRunnersRequest {}

message ListRunnersResponse {
  repeated Runner runners = 1;
}

message AdoptRunnerRequest {
  // ID of the runner to change the adoption status.
  string runner_id = 1;

  // Whether to adopt or reject. True for adopt, false for reject.
  bool adopt = 2;
}

message ForgetRunnerRequest {
  // ID of the runner to forget
  string runner_id = 1;
}

/********************************************************************
* Server
********************************************************************/

message SetServerConfigRequest {
  ServerConfig config = 1;
}

message GetServerConfigResponse {
  ServerConfig config = 1;
}

// ServerConfig is the configuration for the server that can be read and
// set online. This differs from the configuration used to start the server
// since some settings can only be set via the file vs. the API.
message ServerConfig {
  // The addresses that are advertised for entrypoints. These define how
  // applications reach back to the server. Currently you may only set
  // EXACTLY ONE address. In the future, we'll support multiple advertise
  // addrs and more controls over which are advertised when.
  repeated AdvertiseAddr advertise_addrs = 1;

  // The platform that the server is currently installed to. This is set
  // through the CLI flag '-platform' on installation.
  string platform = 4;

  // Cookie is a unique cookie for this server. This can be sent in metadata
  // as a semi-secret mechanism to just ensure you're talking to the correct
  // cluster. The cookie does not enable access to data directly. Some API
  // endpoints (such as RunnerToken) require it. This is auto-generated on
  // startup and cannot currently be changed. Any attempts to change this
  // value are ignored.
  string cookie = 2;

  message AdvertiseAddr {
    string addr = 1;
    bool tls = 2;
    bool tls_skip_verify = 3;
  }
}

/********************************************************************
* Hostnames
********************************************************************/

message CreateHostnameRequest {
  // hostname to register. This may be empty to autogenerate a hostname.
  string hostname = 1;

  // target determines where the hostname routes to.
  Hostname.Target target = 2;
}

message CreateHostnameResponse {
  // Created hostname
  Hostname hostname = 1;
}

message ListHostnamesRequest {
  // Target if set will only return hostnames matching this target.
  // If unset, all hostnames registered for the account will be returned.
  Hostname.Target target = 1;
}

message ListHostnamesResponse {
  repeated Hostname hostnames = 1;
}

message DeleteHostnameRequest {
  string hostname = 1;
}

message Hostname {
  // hostname alone, such as "fabulous-panda"
  string hostname = 1;

  // fqdn is the fully qualified domain, such as "fabulous-panda.waypoint.run"
  string fqdn = 2;

  // target_labels are the raw label targets given to the URL service.
  // We can't reproduce the richer "Target" structure yet but in the future
  // we may expose that.
  map<string, string> target_labels = 3;

  message Target {
    oneof target {
      TargetApp application = 20;
    }
  }

  // TargetApp targets an application in a specific workspace. With
  // this target type, you can still target specific deployments by
  // appending `--<deployment id>` to the hostname after registration.
  message TargetApp {
    Ref.Application application = 1;
    Ref.Workspace workspace = 2;
  }
}

/********************************************************************
* Workspaces
********************************************************************/

message ListWorkspacesRequest {
  // scope of the workspaces to list. If this isn't set, it defaults to
  // "global" for backwards compatibility reasons. Note for that non-global
  // scopes, the workspaces returned may still contain other
  // projects/applications; the scopes guarantee that the workspaces
  // include the project/app/etc. in that scope, however.
  oneof scope {
    // global lists all the workspaces used throughout the entire server.
    google.protobuf.Empty global = 1;

    // project lists all the workspaces in use by any applications in
    // a single project. A workspace returned here is used by 1 or more
    // applications in the project.
    Ref.Project project = 2;

    // application lists all the workspaces in use by a specific application
    // in a project.
    Ref.Application application = 3;
  }
}

message ListWorkspacesResponse {
  repeated Workspace workspaces = 1;
}

message GetWorkspaceRequest {
  Ref.Workspace workspace = 1;
}

message GetWorkspaceResponse {
  Workspace workspace = 1;
}

message UpsertWorkspaceRequest {
  Workspace workspace = 1;
}

message UpsertWorkspaceResponse {
  Workspace workspace = 1;
}

/********************************************************************
* Projects & Apps
********************************************************************/

message UpsertProjectRequest {
  // Project to upsert. See the message for what fields to set.
  Project project = 1;
}

message UpsertProjectResponse {
  Project project = 1;
}

message GetProjectRequest {
  Ref.Project project = 1;
}

message GetProjectResponse {
  Project project = 1;

  // The list of workspaces that this project is part of.
  repeated Workspace.Project workspaces = 2;
}

message ListProjectsResponse {
  repeated Ref.Project projects = 1;
}

message DestroyProjectRequest {
  Ref.Project project = 1;
}

message GetApplicationRequest {
  Ref.Application application = 1;
}

message GetApplicationResponse {
  Application application = 1;
}

message UpsertApplicationRequest {
  // project to register the app against
  Ref.Project project = 1;

  // name of the application to register
  string name = 2;

  // a signal to send the application when config files change
  string file_change_signal = 3;
}

message UpsertApplicationResponse {
  Application application = 1;
}

/********************************************************************
* Build
********************************************************************/

message UpsertBuildRequest {
  // Build to upsert. If an ID is not set, this will be an insert operation.
  // If the ID is set, that build is updated. It is an error if an update
  // is requested on a non-existent build.
  Build build = 1;
}

message UpsertBuildResponse {
  Build build = 1;
}

message ListBuildsRequest {
  // The application whose builds to list. This must be set.
  Ref.Application application = 1;

  // The workspace to list builds for. If this isn't set, then all builds
  // for the other filters are listed.
  Ref.Workspace workspace = 2;

  // Specifies the order of results. If this isn't specified, the results
  // are in an undefined order.
  OperationOrder order = 3;
}

message ListBuildsResponse {
  // builds is the list of builds.
  repeated Build builds = 1;
}

message GetLatestBuildRequest {
  Ref.Application application = 1;
  Ref.Workspace workspace = 2;
}

message GetBuildRequest {
  Ref.Operation ref = 1;
}

// Build represents a process of creating an artifact that can be in any state,
// such as complete. A successful complete build produces an artifact.
message Build {
  // The application that this build is part of.
  Ref.Application application = 6;

  // The workspace that this exists in
  Ref.Workspace workspace = 7;

  // The sequence number for this build.
  uint64 sequence = 8;

  // id is the unique ID of the build
  string id = 1;

  // status of the build
  Status status = 2;

  // component is the component that was used for this build
  Component component = 3;

  // artifact is the result of the build if the status.state == SUCCESS
  Artifact artifact = 4;

  // labels are the set of labels that are present on this build.
  map<string, string> labels = 5;

  // template data for HCL variables and template functions, json-encoded
  bytes template_data = 10;

  // ID of the job that created this build. This may be empty.
  string job_id = 9;

  // Preload is information that is available via further queries but it
  // sometimes pre-populated in the initial load (see the field docs for more
  // info).
  Preload preload = 11;

  message Preload {
    // The ref that was used in the job to run this operation. This is
    // also accessible by querying the job via the job_id and should always
    // match.
    //
    // This may be null under multiple circumstances: (1) the job was
    // manually triggered with local data (no datasource) or (2) the job
    // was run in earlier versions of Waypoint before we tracked this or
    // (3) the job hasn't yet loaded the data.
    //
    // This is always pre-populated if it is exists.
    Job.DataSource.Ref job_data_source_ref = 1;
  }
}

// Artifact is the result of a build or registry. This is the metadata only.
// The binary contents of an artifact are expected to be stored in a registry.
message Artifact {
  // artifact is the full artifact encoded directly from the component plugin.
  // The receiving end must have access to the component proto files to
  // know how to decode this.
  opaqueany.Any artifact = 1;

  // This is the JSON-encoded protobuf structure of the Any field above.
  // This is generated by the plugin and Waypoint core does not modify this
  // value or have any enforced structure. This will be different per-plugin.
  string artifact_json = 2;
}

/********************************************************************
* OnDemand Runners
********************************************************************/
message OnDemandRunnerConfig {
  // id is the unique ID of the runner config
  string id = 1;

  // name is the unique name for this config
  string name = 8;

  // target_runner is the id of the runner to target for this profile.
  // If not set, defaults to use any runner available
  Ref.Runner target_runner = 9;

  // oci_url is the OCI image that will be used to boot the ondemand runner.
  string oci_url = 2;

  // environment_variables is any env vars that should be exposed to the
  // ondemand runner. This does not need to include any WAYPOINT specific
  // variables, those are automatically added.
  map<string, string> environment_variables = 3;

  // plugin type is used to launch the plugin to start the batch task.
  string plugin_type = 4;

  // plugin config is the configuration for the plugin that is created. It
  // is usually HCL and is decoded like the other plugins, and is plugin
  // specific.
  bytes plugin_config = 5;

  // config format specifies the format of plugin_config
  Hcl.Format config_format = 6;

  // Indicates if this entry is the default for any new projects.
  bool default = 7;
}

message UpsertOnDemandRunnerConfigRequest {
  // ondemand_runner to upsert. If the id is empty, then this is an insert,
  // otherwise this is an update operation.
  OnDemandRunnerConfig config = 1;
}

message UpsertOnDemandRunnerConfigResponse {
  // The resulting ondemand runner value. It should replace the one that was
  // sent in the request.
  OnDemandRunnerConfig config = 1;
}

message GetOnDemandRunnerConfigRequest {
  Ref.OnDemandRunnerConfig config = 1;
}

message GetOnDemandRunnerConfigResponse {
  OnDemandRunnerConfig config = 1;
}

message DeleteOnDemandRunnerConfigRequest {
  Ref.OnDemandRunnerConfig config = 1;
}

message DeleteOnDemandRunnerConfigResponse {
  OnDemandRunnerConfig config = 1;
}

message ListOnDemandRunnerConfigsResponse {
  repeated OnDemandRunnerConfig configs = 1;
}

/********************************************************************
* Registry
********************************************************************/

message UpsertPushedArtifactRequest {
  // artifact to upsert. If the id in the artifact is empty, then this
  // will be an insert. Otherwise, this will be an update and if the ID
  // isn't found, it will be an error.
  PushedArtifact artifact = 1;
}

message UpsertPushedArtifactResponse {
  // resulting push object, you should replace this with what was sent
  // since the update operation may touch up the input data (i.e. update
  // timestamps)
  PushedArtifact artifact = 1;
}

message GetLatestPushedArtifactRequest {
  // application that this belongs to
  Ref.Application application = 1;

  // workspace for the artifact, any workspace if empty
  Ref.Workspace workspace = 2;
}

message GetPushedArtifactRequest {
  Ref.Operation ref = 1;
}

message ListPushedArtifactsRequest {
  // application that this belongs to
  Ref.Application application = 3;

  // workspace for the results, or all if not set
  Ref.Workspace workspace = 4;

  // The filters to apply to this request. These are ORed, so you should
  // specify multiple filters in the StatusFilter for AND behavior.
  repeated StatusFilter status = 1;

  // Specifies the order of results. If this isn't specified, the results
  // are in an undefined order.
  OperationOrder order = 2;

  // Indicate if the Build value should be returned for each
  // of the artifacts as well.
  bool include_build = 5;
}

message ListPushedArtifactsResponse {
  // artifacts is the list of artifacts.
  repeated PushedArtifact artifacts = 1;
}

message PushedArtifact {
  // application that this belongs to
  Ref.Application application = 7;

  // The workspace that this exists in
  Ref.Workspace workspace = 8;

  // The sequence number for this build.
  uint64 sequence = 9;

  // id is a unique ID for this push
  string id = 1;

  // status of the push operation
  Status status = 2;

  // component that pushed this artifact
  Component component = 3;

  // artifact is the artifact that was a result from the push.
  Artifact artifact = 4;

  // the id of the build that this pushed artifact was sourced from.
  string build_id = 5;

  // labels are the set of labels that are present on this build.
  map<string, string> labels = 6;

  // template data for HCL variables and template functions, json-encoded
  bytes template_data = 12;

  // If include_build was set on the list request, this will include
  // the Build value associated with the given build_id.
  Build build = 10;

  // ID of the job that created this. This may be empty.
  string job_id = 11;

  // Preload is information that is available via further queries but it
  // sometimes pre-populated in the initial load (see the field docs for more
  // info).
  Preload preload = 13;

  message Preload {
    // The ref that was used in the job to run this operation. This is
    // also accessible by querying the job via the job_id and should always
    // match.
    //
    // This may be null under multiple circumstances: (1) the job was
    // manually triggered with local data (no datasource) or (2) the job
    // was run in earlier versions of Waypoint before we tracked this or
    // (3) the job hasn't yet loaded the data.
    //
    // This is always pre-populated if it is exists.
    Job.DataSource.Ref job_data_source_ref = 1;
  }
}

/********************************************************************
* Platform
********************************************************************/

message GetDeploymentRequest {
  Ref.Operation ref = 1;

  // Indicate if the fetched deployments should include additional information
  // about each deployment.
  Deployment.LoadDetails load_details = 2;
}

message UpsertDeploymentRequest {
  // deployment to upsert. If the id in the artifact is empty, then this
  // will be an insert. Otherwise, this will be an update and if the ID
  // isn't found, it will be an error.
  Deployment deployment = 1;

  // auto_hostname will automatically create a hostname for this app if
  // one doesn't already exist. This hostname maps to the entire app/workspace
  // combo, not specifically to this deployment.
  //
  // This is a "tri-state" boolean because if this is unset then we use
  // the configured defaults for the server configuration.
  Tristate auto_hostname = 2;

  enum Tristate {
    UNSET = 0;
    TRUE = 1;
    FALSE = 2;
  };
}

message UpsertDeploymentResponse {
  // resulting object, you should replace this with what was sent in the request
  // since the update operation may touch up the input data (i.e. update
  // timestamps)
  Deployment deployment = 1;
}

message ListDeploymentsRequest {
  // application that this deployment belongs to
  Ref.Application application = 3;

  // workspace that this should belong to. If this is empty, values in
  // all workspaces will be listed.
  Ref.Workspace workspace = 4;

  // The filters to apply to this request. These are ORed, so you should
  // specify multiple filters in the StatusFilter for AND behavior.
  repeated StatusFilter status = 1;

  // The physical state to filter for. If this is zero or unset then no
  // filtering on physical state will be done.
  Operation.PhysicalState physical_state = 5;

  // Specifies the order of results. If this isn't specified, the results
  // are in an undefined order.
  OperationOrder order = 2;

  // Inidicate of the fetched deployments should include additional information
  // about each deployment.
  Deployment.LoadDetails load_details = 6;
}

message ListDeploymentsResponse {
  // deployments is the list of deployments.
  repeated Deployment deployments = 1;
}

message Deployment {
  // application that this deployment belongs to
  Ref.Application application = 8;

  // The workspace that this exists in
  Ref.Workspace workspace = 9;

  // The sequence number for this build.
  uint64 sequence = 10;

  // id is the unique ID for this deployment
  string id = 1;

  // url is the URL to the Deployment
  // this URL might be empty, indicating that the deployment doesn't have
  // the possibility to be contacted directly (e.g: Kubernetes pod)
  // and thus the URL Service (Hashicorp Horizon) will be used instead, if enabled.
  string url = 18;

  // See the docs for Generation.
  Generation generation = 17;

  // state is the state of this deployment.
  Operation.PhysicalState state = 2;

  // status tracks the status of the most recent operation (creation,
  // destroy, etc. NOTE(mitchellh): I want to separate these out so that
  // you can keep history of the status of multiple operations.
  Status status = 3;

  // component that initiated this deployment
  Component component = 4;

  // ID of the PushedArtifact that was deployed.
  string artifact_id = 5;

  // deployment is the full raw deployment object encoded directly from
  // the plugin. The client must have all the plugins setup to properly
  // decode this.
  opaqueany.Any deployment = 6;

  // This is the JSON-encoded protobuf structure of the Any field above.
  // This is generated by the plugin and Waypoint core does not modify this
  // value or have any enforced structure. This will be different per-plugin.
  string deployment_json = 20;

  // labels are the set of labels that are present on this build.
  map<string, string> labels = 7;

  // template data for HCL variables and template functions, json-encoded
  bytes template_data = 14;

  // ID of the job that created this. This may be empty.
  string job_id = 12;

  // True if this deployment had the environment variables available
  // for the entrypoint to talk to. If this is false, this deployment
  // should not be able to communicate back to the server even if it
  // has the entrypoint available. This means this deployment will not
  // support logs, exec, etc.
  bool has_entrypoint_config = 13;

  // True if the deployment was done by a plugin that defined an exec plugin
  bool has_exec_plugin = 15;

  // True if the deployment was done by a plugin that defined an logs plugin
  bool has_logs_plugin = 16;

  enum LoadDetails {
    NONE = 0;
    ARTIFACT = 1;
    BUILD = 2;
  }

  // Resources that this deployment has created or manages.
  repeated DeclaredResource declared_resources = 19;

  // Resources that a destroy operation has destroyed
  repeated DestroyedResource destroyed_resources = 21;

  // This is the populated preload data. Most of this data can be retrieved
  // through additional API calls or manually computed, but certain API
  // calls will pre-populate some of these fields for convenience. The exact
  // pre-populated fields depend on the API.
  Preload preload = 11;

  message Preload {
    // Populated when a Deployment is read with LoadDetails set
    // to ARTIFACT or BUILD
    PushedArtifact artifact = 1;

    // Populated when a Deployment is read with LoadDetails set to BUILD
    Build build = 2;

    // The deployment-specific URL from the URL service. This is set on
    // all deployment API calls. This will be empty if the URL service
    // is not enabled or there was an error loading this information.
    string deploy_url = 3;

    // The ref that was used in the job to run this operation. This is
    // also accessible by querying the job via the job_id and should always
    // match.
    //
    // This may be null under multiple circumstances: (1) the job was
    // manually triggered with local data (no datasource) or (2) the job
    // was run in earlier versions of Waypoint before we tracked this or
    // (3) the job hasn't yet loaded the data.
    //
    // This is always pre-populated if it is exists.
    Job.DataSource.Ref job_data_source_ref = 4;
  }
}

// A deployment with additional related messages pre-fetched.
message DeploymentExpanded {
  // The deployment in question
  Deployment deployment = 1;

  // The most recent status report generated for this deployment
  StatusReport latest_status_report = 2;
}


/********************************************************************
* Instances
********************************************************************/

message ListInstancesRequest {
  oneof scope {
    // List instances for a specific deployment.
    string deployment_id = 1;

    // Find all instances for an application
    Application application = 2;
  }

  message Application {
    // Application to query. This must have both a project/app set.
    Ref.Application application = 1;

    // Workspace to filter by. If this isn't set, then all workspaces for
    // the app are returned.
    Ref.Workspace workspace = 2;
  }

  // Time to wait before retrying a request to connect to requested instance
  string wait_timeout = 3;
}

message ListInstancesResponse {
  repeated Instance instances = 1;
}

// An instance is a single running process for a deployment. A deployment
// may have many instances (for example Kubernetes ReplicaSets spawn many pods).
// An instance is only represented if you're using the Waypoint Entrypoint.
// Otherwise, the Waypoint server will never be notified of running instances.
message Instance {
  // id of the instance. This should be globally unique to your Waypoint
  // installation but relies on the entrypoint being well behaved.
  string id = 1;

  // The ID of the deployment that this instance belongs to.
  string deployment_id = 2;

  // application that this instance belongs to
  Ref.Application application = 3;

  // The workspace that this exists in
  Ref.Workspace workspace = 4;

  // Which type of instance this is
  Type type = 5;

  // Instances are one of a these types.
  enum Type {
    // The "traditional" instance type, a process that is running
    // constantly for a long period of time.
    LONG_RUNNING = 0;

    // An instance that was launched in response to a request and will
    // disappear quickly.
    ON_DEMAND = 1;

    // An instance that is not actually running any code, but registers
    // itself as an instance for the purposes of interacting with the
    // exec and logs functionality
    VIRTUAL = 2;
  }
}

/********************************************************************
* Release Management
********************************************************************/

message UpsertReleaseRequest {
  // release to upsert. If the id in the artifact is empty, then this
  // will be an insert. Otherwise, this will be an update and if the ID
  // isn't found, it will be an error.
  Release release = 1;
}

message UpsertReleaseResponse {
  // resulting object, you should replace this with what was sent in the request
  // since the update operation may touch up the input data (i.e. update
  // timestamps)
  Release release = 1;
}

message GetLatestReleaseRequest {
  // application that this belongs to
  Ref.Application application = 1;

  // workspace for the artifact, any workspace if empty
  Ref.Workspace workspace = 2;

  // Load additional details about the release. These will become available
  // in the Preload section.
  Release.LoadDetails load_details = 3;
}

message ListReleasesRequest {
  // application that this release belongs to
  Ref.Application application = 3;

  // workspace that this should belong to. If this is empty, values in
  // all workspaces will be listed.
  Ref.Workspace workspace = 4;

  // The filters to apply to this request. These are ORed, so you should
  // specify multiple filters in the StatusFilter for AND behavior.
  repeated StatusFilter status = 1;

  // The physical state to filter for. If this is zero or unset then no
  // filtering on physical state will be done.
  Operation.PhysicalState physical_state = 5;

  // Specifies the order of results. If this isn't specified, the results
  // are in an undefined order.
  OperationOrder order = 2;

  // Load additional details about the release. These will become available
  // in the Preload section.
  Release.LoadDetails load_details = 6;
}

message ListReleasesResponse {
  repeated Release releases = 1;
}

message GetReleaseRequest {
  Ref.Operation ref = 1;

  // Load additional details about the release. These will become available
  // in the Preload section.
  Release.LoadDetails load_details = 2;
}

message Release {
  // application that this release belongs to
  Ref.Application application = 7;

  // The workspace that this exists in
  Ref.Workspace workspace = 8;

  // The sequence number for this build.
  uint64 sequence = 10;

  // id is the unique ID for this release.
  string id = 1;

  // status of the release operation.
  Status status = 2;

  // The physical state of the release resources.
  Operation.PhysicalState state = 11;

  // component managing the release process.
  Component component = 3;

  // release is the raw release object encoded directly from the plugin.
  opaqueany.Any release = 4;

  // This is the JSON-encoded protobuf structure of the Any field above.
  // This is generated by the plugin and Waypoint core does not modify this
  // value or have any enforced structure. This will be different per-plugin.
  string release_json = 16;

  // ID of the deployment that is being released.
  string deployment_id = 5;

  // labels are the set of labels that are present on this build.
  map<string, string> labels = 6;

  // template data for HCL variables and template functions, json-encoded
  bytes template_data = 14;

  // URL for this release. This is valid while the release is still
  // in use. After the release is not in use, this may still be set but
  // may no longer be valid.
  string url = 9;

  // ID of the job that created this. This may be empty.
  string job_id = 13;

  // A boolean to mark this release message as unimplemented by the plugin
  // that generated the message. If true, that means there was not a releaser
  // to execute for the release lifecycle phase.
  bool unimplemented = 15;

  // A platform resource that this release has created, depends on, or manages.
  repeated DeclaredResource declared_resources = 19;

  // Resources that a destroy operation has destroyed
  repeated DestroyedResource destroyed_resources = 20;

  // This is the populated preload data. Most of this data can be retrieved
  // through additional API calls or manually computed, but certain API
  // calls will pre-populate some of these fields for convenience. The exact
  // pre-populated fields depend on the API.
  Preload preload = 12;

  enum LoadDetails {
    NONE = 0;
    DEPLOYMENT = 1;
    ARTIFACT = 2;
    BUILD = 3;
  }

  message Preload {
    // Populated when LoadDetails is set.
    Deployment deployment = 1;

    // Populated when LoadDetails is set.
    PushedArtifact artifact = 2;

    // Populated when LoadDetails is set.
    Build build = 3;

    // The ref that was used in the job to run this operation. This is
    // also accessible by querying the job via the job_id and should always
    // match.
    //
    // This may be null under multiple circumstances: (1) the job was
    // manually triggered with local data (no datasource) or (2) the job
    // was run in earlier versions of Waypoint before we tracked this or
    // (3) the job hasn't yet loaded the data.
    //
    // This is always pre-populated if it is exists.
    Job.DataSource.Ref job_data_source_ref = 4;
  }
}

// A release with additional related messages pre-fetched.
message ReleaseExpanded {
  // The release in question
  Release release = 1;

  // The most recent status report generated for this release
  StatusReport latest_status_report = 2;
}

/********************************************************************
* Trigger URLs
********************************************************************/

// The Trigger message is a representation of a URL that can be requested
// for invoking specific lifecycle operations on a projects applications. These
// trigger URLs are intended to be used in a CI system for easy configuration.
// The user is expected to configure and generate the URL ahead of time, and
// Waypoint will generate a trigger based on the configuration here and return
// a URL to make requests with.
message Trigger {
  reserved 58 to 99; // future operation range

  // uuid generated by Waypoint on creation. Used as the identifier in the URL.
  string id = 1;

  // name can be user defined, or auto generated.
  string name = 2;

  // description is user defined, describes the purpose
  // of the trigger.
  string description = 3;

  // tags that allow users to group triggers together that are
  // related. There are no default tags.
  repeated string tags = 4;

  // time of last execution.
  google.protobuf.Timestamp active_time = 5;

  // whether or not this is authenticated. defaults to true.
  bool authenticated = 6;

  // The operation to execute. See the message docs in Job for details on the operation.
  // This is required, set one (and one only). There is no default.
  // For now, trigger URLs only support lifecycle operations (i.e. up, build, deploy, release)
  oneof operation {
    Job.BuildOp build = 50;
    Job.PushOp push = 51;
    Job.DeployOp deploy = 52;
    Job.DestroyOp destroy = 53;
    Job.ReleaseOp release = 54;
    Job.UpOp up = 55;
    Job.InitOp init = 56;
    Job.StatusReportOp status_report = 57;
  }

  //----------------------------------------------------------------------
  // References to where the operation should take place.
  //----------------------------------------------------------------------

  // Defaults to the default workspace if unset.
  Ref.Workspace workspace = 7;

  // Required. Project ref must be set to be valid trigger URL.
  Ref.Project project = 8;

  // The application to use. Can be empty, this trigger will run on every app
  // if not set.
  Ref.Application application = 9;
}

// Trigger Request Messages

message UpsertTriggerRequest {
  // Trigger URL to upsert. If the id in the message is empty, then this
  // will be an insert. Otherwise, this will be an update. If the ID
  // isn't found, it will be an error.
  Trigger trigger = 1;
}

message UpsertTriggerResponse {
  // The resulting created trigger object after an Upsert.
  Trigger trigger = 1;
}

message GetTriggerRequest {
  Ref.Trigger ref = 1;
}

message GetTriggerResponse {
  Trigger trigger = 1;
}

message DeleteTriggerRequest {
  Ref.Trigger ref = 1;
}

message RunTriggerRequest {
  // The trigger ref to execute
  Ref.Trigger ref = 1;

  // This is an optional array of HCL variable overrides that can be set
  // when requesting a trigger to execute. Currently, RunTrigger only supports
  // setting CLI level config vars, which take the top level of presidence
  repeated Variable variable_overrides = 2;
}

message RunTriggerResponse {
  // the job ID that was queued. This can be used with other RPC methods
  // to check on the status, cancel, etc.
  repeated string job_ids = 1;
}

// ListTriggerRequest can take a handful of optional filter arguments. If none
// are set in the request, this will return all registered trigger URLs in
// the Waypoint server.
message ListTriggerRequest {
  // Defaults to all workspaces if unset.
  Ref.Workspace workspace = 1;

  // Defaults to all projects, can be filtered to a single project if set.
  Ref.Project project = 2;

  // Defaults to all applications in a project, can be filtered to a single application if set.
  Ref.Application application = 3;

  // Will filter triggers by the requested labels if set.
  repeated string tags = 4;
}

message ListTriggerResponse {
  repeated Trigger triggers = 1;
}

/********************************************************************
* Status Reports
********************************************************************/

message UpsertStatusReportRequest {
  // status report to upsert. If the id in the deployment is empty, then this
  // will be an insert. Otherwise, this will be an update and if the ID
  // isn't found, it will be an error.
  StatusReport status_report = 1;
}

message UpsertStatusReportResponse {
  // resulting object, you should replace this with what was sent in the request
  // since the update operation may touch up the input data (i.e. update
  // timestamps)
  StatusReport status_report = 1;
}

message GetLatestStatusReportRequest {
  // application that this belongs to
  Ref.Application application = 1;

  // workspace for the report, any workspace if empty
  Ref.Workspace workspace = 2;

  // Target of the report, will be any if this is not set.
  oneof target {
    google.protobuf.Empty any = 3;
    google.protobuf.Empty deployment_any = 4;
    string deployment_id = 5;
    google.protobuf.Empty release_any = 6;
    string release_id = 7;
  }
}

message ListStatusReportsRequest {
  // The filters to apply to this request. These are ORed, so you should
  // specify multiple filters in the StatusFilter for AND behavior.
  repeated StatusFilter status = 1;

  // Specifies the order of results. If this isn't specified, the results
  // are in an undefined order.
  OperationOrder order = 2;

  // application that this release belongs to
  Ref.Application application = 3;

  // workspace that this should belong to. If this is empty, values in
  // all workspaces will be listed.
  Ref.Workspace workspace = 4;

  // Target is used to determine which status reports to return. By default
  // if no target is requested, the response will include both deployments
  // and release status reports for the requested Application.
  oneof target {
    // the deployment id that this status report was generated on
    Ref.Operation deployment = 5;

    // the release id that this status report was generated on
    Ref.Operation release = 6;
  }
}

message ListStatusReportsResponse {
  repeated StatusReport status_reports = 1;
}

message GetStatusReportRequest {
  Ref.Operation ref = 1;
}

message ExpediteStatusReportRequest {
  // The workspace that this exists in
  Ref.Workspace workspace = 1;

  // Target is used to determine what a status report should be run against
  oneof target {
    // the deployment id that this status report was generated on
    Ref.Operation deployment = 2;

    // the release id that this status report was generated on
    Ref.Operation release = 3;
  }
}

// id of job expedited by the request
message ExpediteStatusReportResponse {
  string job_id = 1;
}

// StatusReport is the report genrated when querying the overall health of
// a deployed or released application. This report is generated after
// an Up Operation, DeployOp or ReleaseOp. In the future Waypoint will be able
// to generate these reports on demand in the UI.
//
// NOTE: This is not related to Status or StatusFilter messages but a message
// used to run the StatusReport job operation for Waypoint Server. The raw SDK
// StatusReport message is stored as an option on this message
message StatusReport {
  // The application that this build is part of.
  Ref.Application application = 1;

  // The workspace that this exists in
  Ref.Workspace workspace = 2;

  // the reference id that is associated with this report
  oneof target_id {
    // the deployment id that this status report was generated on
    string deployment_id = 3;

    // the release id that this status report was generated on
    string release_id = 4;
  }

  // Status of the StatusReport operation executed by the server.
  // Note that this status is not related to the status report, but the current
  // state of the StatusReport operation
  Status status = 5;

  // id is the unique ID for this status report.
  string id = 6;

  // StatusReport is the raw SDK report object encoded directly from the plugin.
  // This message is a StatusReport proto that exists inside the SDK
  opaqueany.Any status_report = 7;
  string status_report_json = 13;

  // The overall health of the deployment or release as reported by the plugin.
  // Copied from the plugin generated raw SDK status report for convenient API access.
  Health health = 8;

  // the time when this report was generated
  // Copied from the plugin generated raw SDK status report for convenient API access.
  google.protobuf.Timestamp generated_time = 10;

  // where the health check was performed. External means not executed by Waypoint,
  // but by the platform deployed to.
  bool external = 11;

  // a collection of resources, e.x. platform resources generated and monitored by a deployment.
  repeated Resource resources = 12;

  // A resource as observed in a platform
  message Resource {
    // The id of the resource, according to the platform.
    string id = 1;

    // declared resource that this directly references.
    Ref.DeclaredResource declared_resource = 2;

    // Resources that created this resource.
    string parent_resource_id = 3;

    // Friendly name of the resource, if applicable
    string name = 4;

    // The platform on which the resource exists.
    string platform = 5;

    // platform-specific name of the resource type. i.e. instance, pod, auto-scaling group, etc
    string type = 6;

    // A link directly to the resource in the platform, if applicable.
    string platform_url = 7;

    // The high level category of the resource, used as a hint to the UI on how to display the resource.
    ResourceCategoryDisplayHint category_display_hint = 8;

    // platform-reported time of resource creation
    google.protobuf.Timestamp created_time = 9;

    // any additional metadata about the resource, encoded as JSON
    string state_json = 10;

    // the current health state for a single resource
    Health health = 13;

    // a simple human readable message detailing the Health state
    string health_message = 12;

    // the state of overall health of a deployed application
    enum Health {
      UNKNOWN = 0;
      ALIVE = 1;
      READY = 2;
      DOWN = 3;
      MISSING = 5; // We're expecting it to exist, but it does not.
      PARTIAL = 4; // Some resources in deployment are OK, others are not OK
    }

    // deprecated in favor of the Health enum and message to match the plugin protos. Was never used.
    StatusReport.Health deprecated_health = 11;
  }

  message Health {
    // the overall health of the report for a resource
    string health_status = 1;

    // the overall health message of the report for a resource
    string health_message = 2;

    string deprecated_name = 3;
    string deprecated_id = 4;
  }

  // Deprecated in favor of resources
  // A health report of all of the resources that make up the report.
  // Copied from the plugin generated raw SDK status report for convenient API access.
  repeated Health deprecated_resources_health = 9;

  // count of active instance connections from waypoint-entrypoint (ceb). This
  // is currently only applicable to deployment type status reports
  uint32 instances_count = 14;
}

/********************************************************************
* Logs
********************************************************************/

message GetLogStreamRequest {
  oneof scope {
    // Deployment to request logs for.
    string deployment_id = 1;

    // Logs for a specific application in a workspace.
    Application application = 2;
  }

  // limit_backlog sets the maximum backlog lines to return on the initial
  // connection. This setting is per instance, not global. The maximum
  // backlog to expect is `n * limit_backlog` where n is the number of
  // instances.
  //
  // A negative value will not limit the backlog.
  //
  // A value of zero will default to a value of 50.
  int32 limit_backlog = 3;

  message Application {
    Ref.Application application = 1;
    Ref.Workspace workspace = 2;
  }
}

message LogBatch {
  string deployment_id = 1;
  string instance_id = 2;
  repeated Entry lines = 3;

  message Entry {
    Source source = 3;
    google.protobuf.Timestamp timestamp = 1;
    string line = 2;

    enum Source {
      // App is zero for backwards compatibility since Source was
      // added later this allows the default to just work.
      APP = 0;

      // Entrypoint logs.
      ENTRYPOINT = 1;
    }
  }
}

/********************************************************************
* Config
********************************************************************/

// ConfigVars represent configuration variables for applications and runners.
// Configuration variables can be exposed via env vars, files, and more. They
// are a way to inject configuration into a Waypoint-managed process.
//
// Note that config vars are different from input variables. Input variables
// are a way to parameterize a Waypoint project/app. This is a different feature.
//
// == Conflict Resolution
//
// When two configuration variables share the same name and are both
// valid for a given target environment (for example, config "foo" set for
// both the project and app scope), the following rules are applied to determine
// which variable value is used:
//
//   1. If a workspace is set one one but not the other, the variable
//      with the workspace sorts higher than no workspace.
//
//   2. The most specific "scope" is used: app over project over global.
//
//   3. If scopes match, the variable with a label selector set is used.
//
//   4. If both have label selectors, the config variable with the longer
//      label selector by string length is used. This is arbitrary but makes
//      the process deterministic.
//
message ConfigVar {
  // Target is the target environment where this config var will take effect.
  Target target = 10;

  // name is the name of the environment variable that this config var is setting
  string name = 1;

  oneof value {
    // unset, if set, unsets this value. For historical reasons, empty static
    // values also unset the value.
    google.protobuf.Empty unset = 7;

    // static, direct value.
    string static = 2;

    // dynamically sourced value
    DynamicVal dynamic = 6;
  }

  // Indicates if the variable is not meant to be exposed applications or runners.
  // It exists only to be referenced by other variables.
  bool internal = 8;

  // Indicates that this is actually be written as a file, with the name
  // field being the filename.
  bool name_is_path = 9;

  // unused_scope is the pre-Waypoint 0.6 fields that are set for
  // setting the scope. This is retained for backwards compatibility
  // but should not be set. Any users of this field should switch to
  // the `target` field.
  oneof unused_scope {
    // These fields used to have docs but removed since they shouldn't be
    // used. If you're really trying to figure how to use these old fields,
    // see a Waypoint 0.5 or earlier git checkout.
    Ref.Application application = 3;
    Ref.Project project = 4;
    Ref.Runner runner = 5;
  }

  // DynamicVal is the configuration for dynamic values for configuration.
  message DynamicVal {
    // from is the config source plugin to use
    string from = 1;

    // config is the configuration for the config source plugin that
    // defines how the value is read. For example, for a "Vault" config
    // source this may contain the path in the KV store to read the value.
    map<string, string> config = 2;
  }

  // Target sets the target where this configuration variable will be set.
  //
  // This has multiple dimensions that filtering can be based on (app scope,
  // runner, workspace, label selectors, etc.). Each of these is optional. If
  // you specify any, they must ALL match.
  //
  // The simplest type of targeting is just for a project. For example, setting
  // an environment variable that is present for all apps in a project, regardless
  // of what workspace it may be in. For this, you'd just set `app_scope` to
  // `project` and leave everything else empty.
  message Target {
    // app_scope is the project/app scope that this config variable will be set.
    // If this is not set, global is assumed.
    oneof app_scope {
      Ref.Global global = 1;
      Ref.Project project = 2;
      Ref.Application application = 3;
    }

    // workspace, if set, will limit this config variable to a specific
    // workspace. This is in addition to the app scoping above. For example,
    // if you specify project scoping above, and set this too, then only
    // matching projects in the matching workspace will have this config var
    // set.
    Ref.Workspace workspace = 4;

    // Label selector specifies an additional filtering mechanism. If this is
    // set, then the labels of the current environment must match for this
    // config variable to be set. Labels are determined by the operation: the
    // labels of the deploy, for example.
    string label_selector = 5;

    // If this is set, then this configuration value will be set on runners
    // instead of deployed applications. This determines the runners that
    // will get this config var. If this config var is for an application,
    // leave this unset (null).
    Ref.Runner runner = 6;
  }
}

message ConfigSetRequest {
  // The set of variables to set. Note that create vs update is determined
  // based on if the targets match, so if you want to change the target of
  // an existing config var you must send two items here: one with a matching
  // target to UNSET it, and one with a new target to set it.
  //
  // Unsets are handled before sets so that a delete will not override a write.
  // All config variables are updated atomically.
  repeated ConfigVar variables = 1;
}

message ConfigSetResponse {}

message ConfigGetRequest {
  // scope is the scoping for this config variable. This describes the
  // target environment requesting configuration. For runners, this may still
  // be set if you are an on-demand runner requesting variables that may be
  // set for runners only in a specific project/app.
  oneof scope {
    Ref.Application application = 2;

    // For project scope, for historical reason, we return all matching
    // config vars (for all apps). We do not merge by name or perform
    // resolution logic. This is how this has always behaved.
    Ref.Project project = 3;
  }

  // Runner is specified if the requesting environment is a runner environment.
  Ref.RunnerId runner = 4;

  // Workspace that the target environment is in. This will limit configuration
  // values to those that are only for this workspace. If this isn't set, all
  // configuration values will be returned.
  Ref.Workspace workspace = 5;

  // Labels that are set in the target environment. This will limit the
  // configuration values to those which have label selectors that match (or
  // those that just ignore labels).
  map<string, string> labels = 6;

  // Get all configuration entries under the given prefix. When empty,
  // returns all config variables.
  string prefix = 1;
}

message ConfigGetResponse {
  repeated ConfigVar variables = 1;
}

/********************************************************************
* Config Sources
********************************************************************/

message ConfigSource {
  // delete may be set to true on SetConfigSource to delete this config source.
  // This is a field on ConfigSource since there are a variety of ways to
  // identify a ConfigSource. Therefore, the recommend deletion process is
  // to query the ConfigSource using GetConfigSource and then set delete
  // on a return value to ensure the correct value is deleted.
  bool delete = 3;

  // Scope that this configuration is valid. Note that this doesn't
  // prevent a config source from being used in other scopes, it only
  // prevents this configuration. Configuration sources used in other
  // scopes will use a default configuration set by the plugin.
  oneof scope {
    Ref.Global global = 50;
  }

  // type of the config source. This should match the plugin name.
  string type = 1;

  // config is the configuration for the config source.
  map<string, string> config = 2;

  // hash is set automatically on write and available on read and is a
  // content hash of the configuration. This can be used to determine
  // uniqueness or changes in the configuration. Setting this value with
  // SetConfigSource has no effect and will be overwritten. Note that this
  // hash may take more into account than just "config" as other fields
  // are introduced to this message type.
  uint64 hash = 4;
}

message SetConfigSourceRequest {
  ConfigSource config_source = 1;
}

message GetConfigSourceRequest {
  // scope is the scoping for the config source.
  oneof scope {
    Ref.Global global = 50;
  }

  // config source type. This is optional. If this is omitted, all
  // config source types matching the above scoping will be returned.
  // This is a prefix-search. All config sources with this type prefix
  // will be returned.
  string type = 1;
}

message GetConfigSourceResponse {
  repeated ConfigSource config_sources = 1;
}

/********************************************************************
* Exec
********************************************************************/

message ExecStreamRequest {
  oneof event {
    Start start = 1;
    Input input = 2;
    WindowSize winch = 3;

    // input_eof should be sent as an event when the input stream is
    // closed. After this, no more Input messages can be sent. Any Input
    // messages sent will be ignored. This will send an EOF on the remote
    // end as well to close stdin for the exec process.
    google.protobuf.Empty input_eof = 4;
  }

  message Start {
    oneof target {
      // Deployment to exec into
      string deployment_id = 1;

      // Instance to send the exec request to. This is indicates that
      // the client wants an exec session to this specific instance,
      // rather than one the server picks. Targeted instances can be
      // any instance type, where as untargeted have to be LONG_RUNNING.
      string instance_id = 4;
    }

    // Args including the command at args[0] to execute.
    repeated string args = 2;

    // Pty is set if we should allocate a PTY for this exec stream.
    PTY pty = 3;
  }

  message Input {
    bytes data = 1;
  }

  message PTY {
    bool enable = 1;

    // term is the TERM value to request on the remote side. This should be set.
    string term = 2;

    // window_size is the initial window size
    WindowSize window_size = 3;
  }

  message WindowSize {
    int32 rows = 1;
    int32 cols = 2;
    int32 width = 3;
    int32 height = 4;
  }
}

message ExecStreamResponse {
  oneof event {
    // Open is always sent first no matter what (unless there is an error
    // in which case the stream will exit). This should be used to validate
    // that the exec process started properly.
    Open open = 3;

    Output output = 1;
    Exit exit = 2;
  }

  message Open {}

  message Exit {
    int32 code = 1;
  }

  message Output {
    Channel channel = 1;
    bytes data = 2;

    enum Channel {
      UNKNOWN = 0;
      STDOUT = 1;
      STDERR = 2;
    }
  }
}

/********************************************************************
* Entrypoint
********************************************************************/

message EntrypointConfigRequest {
  // id of the deployment that this instance is a part of
  string deployment_id = 1;

  // instance_id is a unique ID generated by the running entrypoint. This is
  // not an auth mechanism, just a way to associate data with the correct instance.
  string instance_id = 2;

  // The type of instance that is making the config request. This type will be
  // recorded by the server to alter how the server interacts with the instance.
  Instance.Type type = 3;

  // If this is true, then this instance will never be assigned any exec
  // sessions. If no instances support exec, an error will be shown to the
  // user.
  bool disable_exec = 4;
}

message EntrypointConfigResponse {
  EntrypointConfig config = 2;
}

message EntrypointConfig {
  // Exec are requested exec sessions for this instance.
  repeated Exec exec = 1;

  // The environment variables to set in the entrypoint.
  repeated ConfigVar env_vars = 2;

  // The configuration for any config sources that may be used in the
  // config vars sent down. The server may send down extra configs that
  // aren't used so consumers should filter these based on what env vars
  // are actually in use.
  repeated ConfigSource config_sources = 5;

  // The signal to send the application when config files change.
  string file_change_signal = 6;

  // The URL service configuration. This might be nil. If this is nil,
  // then the URL service is disabled.
  URLService url_service = 3;

  // Deployment is the deployment information for this instance. This may
  // be nil if the user is running an old enough server so always nil-check this.
  DeploymentInfo deployment = 4;

  message Exec {
    int64 index = 1;
    repeated string args = 2;
    ExecStreamRequest.PTY pty = 3;
  }

  message URLService {
    // address to the control server and the token for auth
    string control_addr = 1;
    string token = 2;

    // labels to register this instance under
    string labels = 3;
  }

  message DeploymentInfo {
    // component is the deployment plugin information that launched this instance.
    Component component = 1;

    // labels are the set of labels that are present on the deployment.
    map<string, string> labels = 2;
  }
}

// A batch of data for log streaming from the entrypoint.
message EntrypointLogBatch {
  // instance_id is a unique ID generated by the running entrypoint. This is
  // not an auth mechanism, just a way to associate data with the correct instance.
  string instance_id = 1;

  // lines is the set of lines
  repeated LogBatch.Entry lines = 2;
}

message EntrypointExecRequest {
  oneof event {
    // open MUST BE the first message sent by a client. This will be used
    // by the server side to perform some initialization. If the first message
    // is not open the server will close the connection.
    Open open = 1;

    // exit should be sent as a final message type after the command exits.
    Exit exit = 2;

    // output contains stdout/stderr
    Output output = 3;

    // error indicates an error occurred. This will terminate the stream.
    Error error = 4;
  }

  message Open {
    string instance_id = 1;
    int64 index = 2;
  }

  message Exit {
    int32 code = 1;
  }

  message Output {
    Channel channel = 1;
    bytes data = 2;

    enum Channel {
      UNKNOWN = 0;
      STDOUT = 1;
      STDERR = 2;
    }
  }

  message Error {
    google.rpc.Status error = 1;
  }
}

message EntrypointExecResponse {
  oneof event {
    // input is raw stdin input from the client
    bytes input = 1;

    // input_eof means that stdin is now closed
    google.protobuf.Empty input_eof = 4;

    // winch is SIGWNCH information for window sizing
    ExecStreamRequest.WindowSize winch = 2;

    // opened is sent when the entrypoint session is successfully opened.
    // The value of this message is meaningless. The existence of the message
    // itself is a signal that the stream was opened properly.
    bool opened = 3;
  }
}

/********************************************************************
* Pipelines
********************************************************************/

message Pipeline {
  // Unique ID for this pipeline.
  string id = 1;

  // Human-friendly name for the pipeline. This is not unique! Users should
  // use the ID and other metadata to differentiate pipelines. In general,
  // we recommend avoiding reusing names.
  string name = 2;

  // The owner is the thing that manages this pipeline.
  //
  // NOTE(mitchellh): We currently only support project-synced pipelines.
  // In the future, we may want to consider pipelines not attached to
  // projects (just created via the API/UI/CLI on their own). This "oneof"
  // is here to represent that. If we ever decide NOT to do that, we can just
  // remove the "oneof" which is backwards compatible.
  oneof owner {
    // This pipeline is created from a waypoint.hcl file that is synced via VCS.
    Ref.Project project = 3;
  }

  // The steps that make up this pipeline. This is a set and the order
  // has no meaning; it does not imply any ordering that the steps will
  // be executed. The execution order is purely defined by the "depends_on"
  // fields on the steps.
  //
  // There must be only one "root" step. A root step is a step with no
  // dependencies. It is an error for there to be more than one root step.
  //
  // For API users, the GetPipelineResponse has a number of fields that
  // help make this much easier to consume, such as a dedicated field for
  // the root step, mermaid-formatted graph output, and more.
  //
  // These requirements are usually hidden from users through nicer user
  // experiences for editing: waypoint.hcl syntax (which implicitly creates
  // ordering and root steps), UIs, etc. All these requirements are noted for
  // _internal_ users who are modifying pipelines via the API. For those
  // internal users, they must manage the tedium of adhering to these requirements.
  map<string, Step> steps = 4;

  // A single step within the pipeline.
  message Step {
    // Name of the step. This is unique within a pipeline. In the "steps"
    // map, this must match the map key.
    string name = 1;

    // The steps that must come before this step. If this is empty,
    // this is considered a "root" step. Only one step may be root.
    // See "steps" on the Pipeline message for details.
    repeated string depends_on = 2;

    // The kind of step this is. IMPORTANT: the string values stored
    // by the kind messages may contain HCL that needs further parsing.
    // They are "partially" evaluated (similar to ConfigVars) using
    // internal/pkg/partial.
    oneof kind {
      // Docker execute.
      Exec exec = 3;

      //
      // "reserved" built-in pipeline step operations. These map directly to
      // the lifecycle operations in Waypoint, i.e. Build, Deploy, Release, Up.
      //

      // Built-in build operation
      Build build = 4;

      // Built-in deploy operation
      Deploy deploy = 6;

      // Built-in release operation
      Release release = 7;

      // Built-in up operation
      Up up = 8;

      // A reference to a different pipeline
      Pipeline pipeline = 9;

      // TODO: custom plugins, pipeline references
    }

    // Docker image to execute. This should be a fully qualified image URL.
    string image = 5;

    // Workspace to use in step execution. If undefined, will default to the
    // Workspace used when running the pipeline, otherwise 'default'
    Ref.Workspace workspace = 10;

    message Exec {
      // TODO(briancain): update this to use the Step exec instead of the plugin
      // Docker image to execute. This should be a fully qualified image URL.
      string image = 1;

      // Command to execute within the image. If blank, the default command
      // will be executed.
      string command = 2;
      repeated string args = 3;
    }

    message Build {
      // Whether or not to push the built artifact to a remote container registry
      // TODO(briancain): ensure default to false because this will be inside
      // an ODR container
      bool disable_push = 2;
    }

    message Deploy {
      // Whether or not to run a release immediately after the deploy. Defaults
      // to false. Users would probably write a Release step to opt into a release
      // but lets support the option here just like the CLI does.
      bool release = 1;
    }

    message Release {
      Ref.Deployment deployment = 1;
      bool prune = 2;

      // This sets the number of unreleased deployments to retain when pruning.
      // This only has an effect if "prune_retain_override" is true. If that
      // is false, then pruning uses the default behavior (retain 2).
      int32 prune_retain = 3;
      bool prune_retain_override = 4;
    }

    message Up {
      bool prune = 1;

      // This sets the number of unreleased deployments to retain when pruning.
      // This only has an effect if "prune_retain_override" is true. If that
      // is false, then pruning uses the default behavior (retain 2).
      int32 prune_retain = 2;
      bool prune_retain_override = 3;
    }

    message Pipeline {
      Ref.Pipeline ref = 1;
    }
  }
}

message PipelineRun {
  string id = 1;
  // The sequence number for this pipeline run.
  uint64 sequence = 2;

  Ref.Pipeline pipeline = 3;

  repeated Ref.Job jobs = 4;

  State state = 5;

  enum State {
    UNKNOWN = 0; // no state defined, the default
    PENDING = 1; // pipeline run created
    STARTING = 2; // root_job queued
    RUNNING = 3; // jobs are working
    ERROR = 4; // when any job errors, the pipeline aborts
    CANCELLED = 5; // when any job gets manually cancelled, the entire pipeline aborts
    SUCCESS = 6; // last_job completed
  }
}

message UpsertPipelineRequest {
  Pipeline pipeline = 1;
}

message UpsertPipelineResponse {
  // This is the inserted/updated pipeline. This may not match the
  // input since this will contain fully normalized data.
  Pipeline pipeline = 1;
}

message GetPipelineRequest {
  Ref.Pipeline pipeline = 1;
}

message GetPipelineResponse {
  // Pipeline is the pipeline that was requested.
  Pipeline pipeline = 1;

  // Root step is the name of the step in pipeline that is the first
  // step executed.
  string root_step = 2;

  // Graph is the execution graph for the pipeline steps. This can be
  // used to better visualize pipeline execution since the internal data
  // format of pipeline.steps is optimized more for storage rather than usage.
  Graph graph = 3;

  // Graph represents the execution graph for the pipeline steps. This
  // may support multiple formats.
  message Graph {
    bytes content = 1;
    Format format = 2;

    enum Format {
      INVALID = 0;
      MERMAID = 1; // https://mermaid-js.github.io/mermaid/
    }
  }
}

message RunPipelineRequest {
  // The pipeline to execute.
  Ref.Pipeline pipeline = 1;

  // This is the job template to use for all the queued steps. This should
  // set all the required fields of a job except for "operation".
  Job job_template = 2;

  // In the future, we'll put input variables and other options here.
}

message RunPipelineResponse {
  // The root job of the pipeline.
  string job_id = 1;

  // All job IDs are the list of all jobs that were queued for this pipeline.
  // They are in topologically sorted order. This means that a job's dependencies
  // are guaranteed to be satisfied by previous jobs in the list, but all
  // previous jobs may not be necessary. This is because two jobs may be
  // totally independent of each other and can execute concurrently. To get
  // a better view, a graph should be built using step dependencies, and
  // the job IDs can be correlated using the job_map field.
  repeated string all_job_ids = 2;

  // This provides a lookup from job ID to what step and pipeline a job
  // corresponds to. Note that some jobs may correspond to pipelines other
  // than the initial pipeline if nested pipelines are used.
  map<string, Ref.PipelineStep> job_map = 3;

  uint64 sequence = 4;
}

message ListPipelinesRequest {
  // The project to list all pipelines on
  Ref.Project project = 1;
}

message ListPipelinesResponse {
  // All of the listed pipelines
  repeated Pipeline pipelines = 1;
}

// NOTE(xx): these requests will be refactored in a future PR to optimize for UI
// Will also add PipelineBundle and PipelineRunBundle objects
message ListPipelineRunsRequest {
  Ref.Pipeline pipeline = 1;
}

message ListPipelineRunsResponse {
  // All of the listed pipelines
  repeated PipelineRun pipeline_runs = 1;
}

message GetPipelineRunRequest {
  Ref.Pipeline pipeline = 1;
  uint64 sequence = 2;
}

message GetPipelineRunResponse {
  // A single pipeline run
  PipelineRun pipeline_run = 1;
}

message ConfigSyncPipelineRequest {
  // The project to sync all pipeline configs on
  Ref.Project project = 1;
}

message ConfigSyncPipelineResponse {
  // synced_pipelines is a map of Pipeline Name Keys to Pipeline ID Refs for
  // each pipeline that was synced in the config sync request.
  map<string, Ref.Pipeline> synced_pipelines = 1;
}

/********************************************************************
* Token
********************************************************************/

// The outer structure of the token that is directly Marshaled and
// ASCII armored.
message TokenTransport {
  // A Marshaled token, stored as bytes because we need to to validate
  // it with the given signature.
  bytes body = 1;

  // The signature of body for validation.
  bytes signature = 2;

  // The key used to generate the signature.
  string key_id = 3;

  // Any configuration style metadata that can be passed along with the token
  // without invalidating the token body itself.
  map<string, string> metadata = 4;

  // The external creds are stored outside of the authenticated token body
  // because we want clients that see the creds in the transport to use
  // them BUT then strip them out before transmitting the token, so that
  // the creds aren't be transfer constantly.
  oneof external_creds {
    // A client that sees this populated will use the details to fetch a token
    // via oauth instead of submitting this token directly.
    OAuthCredentials oauth_creds = 12;
  }

  // The OAuth message contains information that the client should use
  // to generate on OAuth token for authenticating with the server rather
  // than just submitting the waypoint token directly.
  message OAuthCredentials {
    // The url for the oauth2 provider
    string url = 1;

    // The OAuth client id to submit
    string client_id = 2;

    // The OAuth client secret that goes along with the client_id
    string client_secret = 3;
  }
}

// The authenticated Token information. This is used to authenticate requests.
message Token {
  // Non-secret ID that is used in logs to represent this token. Internally,
  // this is also used as a nonce when signing. This ID is randomly generated
  // when created.
  bytes accessor_id = 2;

  // When the token is valid until. After the given date, the token will be
  // rejected. When this is not set, the token is valid forever.
  google.protobuf.Timestamp valid_until = 3;

  // When the token was issued. This may be used for revocation using a
  // "no earlier than" rule.
  google.protobuf.Timestamp issued_time = 7;

  // The kind of token this is.
  oneof kind {
    // login tokens can be used for API requests
    Login login = 8;

    // Runner tokens can be used to request work on behalf of a runner.
    // They have full API access as well since the workloads that runners
    // run currently reuse this token.
    Runner runner = 11;

    // invite tokens can be exhanged for login tokens and also optionally
    // sign a new user up.
    Invite invite = 9;

    // trigger tokens can be used to trigger lifecycle actions via HTTP
    Trigger trigger = 10;
  }

  message Login {
    // User that this token represents. This is the internal user ID (ULID),
    // not the username/email/etc. The special value of "waypoint" means the
    // superuser (default user) that is setup on bootstrap. This is for
    // historical reasons only and is the only valid non-ULID value.
    string user_id = 1;

    // If set, this login token can only be used for entrypoint-related
    // APIs against the configured deployment.
    Entrypoint entrypoint = 2;
  }

  message Runner {
    // Id is the exact ID to match for this token. If a runner with another
    // ID attempts to use this token, it will reject it. This can be blank
    // to allow any ID.
    string id = 1;

    // If non-zero, the label set of the runner must hash to the same value
    // for this token to be active. This prevents runners changing their
    // labels after adoption (i.e. to go from targeting dev to prod).
    uint64 label_hash = 2;
  }

  message Invite {
    // The user that initiated the invite
    string from_user_id = 1;

    // The login token we'd like to create. This can be used to setup
    // all the policy attachments and other restrictions. If this is a
    // signup-only invite token, then "user_id" in this login field will
    // be ignored and set to the newly created user ID.
    Login login = 2;

    // Signup, if non-nil, makes this invite a signup-only invite token. This
    // means that this token can only be used to create a new account, not
    // to exchange for a token for an existing account.
    Signup signup = 3;

    message Signup {
      // The initial username that the new user should be given. If this
      // username is taken, a random number will be appended. If this is
      // empty, a totally random username will be given to the new user.
      string initial_username = 1;
    }
  }

  message Entrypoint {
    // deployment id is the deployment to restrict this token to.
    string deployment_id = 1;
  }

  // The Trigger message is a kind of token type that is only used for
  // authenticated trigger URL requests. It should not have any other
  // authorized access to make requests in any other API endpoint.
  message Trigger {
    // The user that initiated the trigger token generation
    string from_user_id = 1;
  }

  // OLD FIELDS FOR BACKWARDS COMPATIBILITY. These are no longer used
  // for new tokens, please do not attempt to read them. Any calls to
  // DecodeToken API will automatically convert old tokens to the new
  // style so callers should never see these set.

  // The user that the token is for. This must be "waypoint" for
  // backwards compat reasons.
  string unused_user = 1;

  // Old way to determine what kind of token this is.
  bool unused_login = 4;
  bool unused_invite = 5;

  // Same as Login.entrypoint, we just moved it.
  Entrypoint unused_entrypoint = 6;
}

// Represents a key used to sign tokens using HMAC
message HMACKey {
  // The identifier of the key.
  string id = 1;

  // A randomly generated key used to sign tokens with
  bytes key = 2;
}

message DecodeTokenRequest {
  // The token to decode.
  string token = 1;
}

message DecodeTokenResponse {
  // The decoded token.
  Token token = 1;

  // Transport is the wrapper around the token. This may be useful
  // to look into the metadata around the token.
  TokenTransport transport = 2;
}

message LoginTokenRequest {
  // How long the token should be valid from the time the request
  // is made. If this is empty then the login token never expires on its own.
  string duration = 1;

  // The user to create the login token for. If this is nil, the currently
  // logged in user is used. The calling user must have permission to create
  // a token for the target user if this is set.
  Ref.User user = 2;

  // The token generated will only be used for Trigger URL actions. The token
  // will not be authorized to make any other requests to any other endpoints
  bool trigger = 3;
}

message GenerateRunnerTokenRequest {
  // How long the token should be valid from the time the request
  // is made. If this is empty then the runner token never expires on its own.
  string duration = 1;

  // ID to restrict this token to work with. This can be empty to allow it
  // for all runner IDs.
  string id = 2;

  // The set of labels to restrict this runner token to work for. The runner
  // labels must match this label set exactly. If this is not set, then runners
  // with any labels may use the resulting token.
  map<string, string> labels = 3;
}

// Passed with GenerateInviteToken with the params on how the invite token should
// be generate.
message InviteTokenRequest {
  // How long the token should be valid until. The resulting token has a timestamp
  // encoded within it by adding the current time to this duration.
  string duration = 1;

  // login is the login information you want this token exchange for. All fields
  // can be set (including logging in as another user as long as the requesting
  // user has permission). If this is a signup invite token, the "user_id"
  // will be ignored.
  Token.Login login = 4;

  // signup, if non-nil, will exchange this invite token for new user accounts.
  // The signup structure can be used to hint for the username. This must be
  // non-nil for this to be a signup token for new accounts.
  Token.Invite.Signup signup = 3;

  // Old field, used only for backwards compatibility. If this is set,
  // the old behavior will be followed. If you don't know what that is,
  // then do not use this field.
  Token.Entrypoint unused_entrypoint = 2;
}

// Returned by any action that creates a token.
message NewTokenResponse {
  // The new token which can be presented to whichever API expects it.
  string token = 1;
}

// Passed to ConvertInviteToken to create a new token that can be used to authenticate RPCs.
message ConvertInviteTokenRequest {
  // A token previous returned by GenerateInviteToken.
  string token = 1;
}

/********************************************************************
* Snapshot/Restore
********************************************************************/

message CreateSnapshotResponse {
  oneof event {
    // Open is sent as the opening message with information about the
    // snapshot. This is always sent first (before any data).
    Open open = 1;

    // Chunk is a next chunk of data. You should continue to expect
    // data until an EOF is received on the stream.
    bytes chunk = 2;
  }

  // One day we may add information here. For now we are reserving this.
  message Open {}
}

message RestoreSnapshotRequest {
  oneof event {
    // Open MUST be sent as the first message and sent exactly once.
    // This sets the settings for the restore.
    Open open = 1;

    // Chunk is a chunk of restore data. The restore snapshot API will
    // continue reading data until an EOF is received (the write end is
    // closed).
    bytes chunk = 2;
  }

  message Open {
    // If true, the server will exit after the restore is staged. This will
    // SHUT DOWN the server and some external process you created is expected
    // to bring it back. The Waypoint server on its own WILL NOT automatically
    // restart. You should only set this if you have some operation to
    // automate restart such as running in Nomad or Kubernetes.
    bool exit = 1;
  }
}

// Snapshot is the encoding of the snapshot for all snapshot APIs.
// The encoding is proto.Message delimited data. This is also the encoding
// expected if the waypoint-restore.db file is copied manually from the
// snapshot data.
//
// For snapshots, the Header message is always guaranteed first. After that,
// it is NOT guaranteed that only data chunks are sent. It is only guaranteed
// that the data chunks are over at EOF. Unknown messages can probably be
// ignored.
//
// It is HIGHLY RECOMMENDED you do not modify snapshots, but these messages
// are publicly exported so that you can try to inspect snapshots.
message Snapshot {
  // Header is _always_ the first message encoded into a snapshot. If
  // this isn't present, the entire snapshot can be considered corrupt.
  message Header {
    // version is the version of Waypoint that generated this snapshot.
    VersionInfo version = 1;

    // format is the format of the remaining messages. This can be used
    // to determine what messages to expect following the header.
    Format format = 2;

    enum Format {
      UNKNOWN = 0;
      BOLT = 1; // Expect a series of BoltChunk messages
    }
  }

  // Trailer is sent as the final message encoded into a snapshot. Detecting
  // when the trailer is is dependent on the format.
  message Trailer {
    // checksum is the checksum of all the bytes up to but not including
    // this proto message. The checksum is for the raw uncompressed bytes.
    oneof checksum {
      string sha256 = 1; // SHA-256 checksum
    }
  }

  // BoltChunk is a single chunk of data for BoltDB if the snapshot format
  // is BOLT. A chunk will always contain items designated for a single bucket,
  // but a bucket may be repeated multiple time across chunks if there are
  // too many items in the bucket.
  //
  // The final BoltChunk will have trailer set to true. Immediaetly following
  // that chunk will be the Trailer message.
  message BoltChunk {
    // bucket is the name of the bucket. This may be empty. If this is empty,
    // then this chunk should be ignored.
    string bucket = 1;

    // items is a id/value mapping of all this chunk of items in this bucket
    map<string, bytes> items = 2;

    // final is true if this is the last bolt chunk being written.
    bool final = 3;
  }
}

/********************************************************************
* Waypoint.hcl Helpers
********************************************************************/

// Hcl is a message used to encapsulate the contents of an HCL
// file. Note that this was introduced later so there are some message types
// that reproduce this functionality without actually using this in order
// to maintain backwards compatibility.
message Hcl {
  // Raw contents of the HCL file.
  bytes contents = 1;

  // Format of HCL contents
  Format format = 2;

  // HCL files can be in either HCL or JSON syntax. We need to know ahead of
  // time in order to parse it properly. We could perform heuristics but
  // we prefer to be explicit.
  enum Format {
    HCL = 0; // We assume HCL by default
    JSON = 1;
  }
}

message WaypointHclFmtRequest {
  bytes waypoint_hcl = 1;
}

message WaypointHclFmtResponse {
  bytes waypoint_hcl = 1;
}

/********************************************************************
* Util/Meta
********************************************************************/

// InlineKeepalive is a message intended to be sent down existing grpc streams
// to induce traffic and prevent them from being idle terminated by load
// balancers that do not respect http2 pings. They will be sent on streams
// that do not have this message as part of their protobuf contract. Client and
// server grpc interceptors intercept these messages and prevent them from being
// exposed to the rpc handlers.
message InlineKeepalive {
  // Signature for validating that the message is, in fact, a keepalive message.
  // Must be set to value "inline_keepalive".

  // WARNING: NO OTHER MESSAGE MAY USE THIS FIELD NUMBER. Doing so will cause
  // that message to be confused with an inline keepalive
  string signature = 100000000;
}
