Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/bitdrift_public/protobuf/bdtail/v1/bdtail_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,36 @@ package bitdrift_public.protobuf.bdtail.v1;
import "bitdrift_public/protobuf/matcher/v1/log_matcher.proto";
import "validate/validate.proto";

// Requests that a device execute a command through a BDTail configuration.
message DeviceCommandRequest {
// Requests the device's buffered logs.
message DumpDeviceBufferCommand {}

// Requests the device's current screen as a JPEG image.
message TakeScreenshotCommand {}

// Requests an opaque command handled by a client-registered definition.
message CustomCommand {
string command_definition_id = 1 [(validate.rules).string.uuid = true];
}

// The command ID generated by the server.
string command_id = 1 [(validate.rules).string.uuid = true];

oneof command_type {
option (validate.required) = true;

// Requests the device's buffered logs.
DumpDeviceBufferCommand dump_device_buffer = 2;

// Requests the device's current screen as a JPEG image.
TakeScreenshotCommand take_screenshot = 3;

// Requests an opaque client-registered command.
CustomCommand custom_command = 4;
}
}

message BdTailStream {
// The name of the bdtail stream. Logs that match the matcher below should be annotated with this
// stream ID to allow the SaaS to associate the log with the bdtail stream.
Expand All @@ -20,6 +50,9 @@ message BdTailStream {
// The match criteria for logs that should be forwarded to this bdtail stream. If empty, all logs
// will be forwarded to this stream.
matcher.v1.LogMatcher matcher = 2;

// An optional remote command to execute. Its command_id equals stream_id when present.
DeviceCommandRequest device_command = 3;
}

message BdTailConfigurations {
Expand Down
82 changes: 82 additions & 0 deletions src/bitdrift_public/protobuf/client/v1/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,15 @@ message LogUploadIntentResponse {

// A single log upload payload.
message LogUploadRequest {
// Identifies a buffer-dump command whose persisted log bytes this upload contributes to.
message DeviceCommandProgress {
// The command ID from the corresponding DeviceCommandRequest.
string command_id = 1 [(validate.rules).string.uuid = true];

// The immutable total number of result payload bytes expected from the command.
uint64 total_result_bytes = 2;
}

// A UUID (v4) associated with this upload. This should be generated by the
// client. Retries should use the same upload_id.
string upload_uuid = 1 [(validate.rules).string = {min_len: 1}];
Expand Down Expand Up @@ -257,6 +266,10 @@ message LogUploadRequest {
// throughput, low value logs where the client does not need to know whether
// the upload succeeded or failed.
bool ackless = 4;

// Command progress metadata for a buffer-dump upload. The outer upload_uuid is its stable
// per-batch idempotency key.
DeviceCommandProgress device_command_progress = 7;
}

// Empty message to maintain a application layer keep alive mechanism.
Expand Down Expand Up @@ -308,6 +321,7 @@ message ApiRequest {
UploadArtifactIntentRequest artifact_intent = 13;
DebugDataRequest debug_data = 14;
StateUpdateRequest state_update = 15;
DeviceCommandUpdate device_command_update = 16;
}

reserved 8;
Expand Down Expand Up @@ -419,6 +433,10 @@ message UploadArtifactRequest {
// Client workflow continuations that should be evaluated when this report is processed.
// Only populated for issue-report artifacts; other artifact types must leave this unset.
optional workflow.v1.WorkflowReportHandoff workflow_report_handoff = 9;

// The remote command that produced this artifact. Only command-correlated artifact uploads set
// this field; workflow command artifacts remain session artifacts and leave it unset.
optional string command_id = 10 [(validate.rules).string.uuid = true];
}

message UploadArtifactResponse {
Expand Down Expand Up @@ -668,6 +686,69 @@ message FlushBuffers {
workflow.v1.Workflow.Action.ActionFlushBuffers.Streaming streaming = 2;
}

// Structured data supplied with a terminal device command result. Artifact bytes are uploaded
// separately through `UploadArtifactRequest` and must not be included in this context.
message DeviceCommandResultContext {
// Command- or transport-supplied fields describing the terminal result. Binary values are
// rejected; artifacts must use `UploadArtifactRequest`.
map<string, logging.v1.Data> fields = 1 [(validate.rules).map.max_pairs = 100];
}

// Reports an update from a device command.
message DeviceCommandUpdate {
// Confirms that the device accepted the command.
message Accepted {
// The immutable total number of result payload bytes expected from the command.
optional uint64 total_result_bytes = 1;
}

// Confirms that the command completed successfully.
message Completed {
// Whether output was limited before the command completed.
bool output_truncated = 1;

// Optional structured context supplied with the successful command result.
DeviceCommandResultContext context = 2;
}

// Reports that command execution could not be completed.
message Failed {
// Optional structured context supplied with the failed command result.
DeviceCommandResultContext context = 1;
}

// The command ID from the corresponding DeviceCommandRequest.
string command_id = 1 [(validate.rules).string.uuid = true];

// The monotonically increasing sequence number for this command update.
uint64 update_sequence_number = 2;

oneof update_type {
option (validate.required) = true;

// Confirms that the device accepted the command.
Accepted accepted = 3;

// Confirms that the command completed successfully.
Completed completed = 4;

// Reports that command execution could not be completed.
Failed failed = 5;
}
}

// Acknowledges that the server persisted a command update.
message DeviceCommandUpdateAck {
// The command ID from the corresponding DeviceCommandRequest.
string command_id = 1 [(validate.rules).string.uuid = true];

// The command update sequence number that was persisted.
uint64 update_sequence_number = 2;

// A non-empty error means the server did not persist the update and the client should retry it.
string error = 3;
}

// The response to Sankey diagram path upload request.
message SankeyPathUploadResponse {
// The UUID corresponding to the upload request.
Expand Down Expand Up @@ -758,6 +839,7 @@ message ApiResponse {
UploadArtifactResponse artifact_upload = 14;
UploadArtifactIntentResponse artifact_intent = 15;
StateUpdateResponse state_update = 16;
DeviceCommandUpdateAck device_command_update_ack = 17;
}

reserved 10;
Expand Down
3 changes: 3 additions & 0 deletions src/bitdrift_public/protobuf/client/v1/artifact.proto
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ message ArtifactUploadIndex {
// Client workflow continuations that should be evaluated when this report is processed.
// Only populated for issue-report artifacts; other artifact types must leave this unset.
optional bitdrift_public.protobuf.workflow.v1.WorkflowReportHandoff workflow_report_handoff = 10;

// The remote command that produced this artifact. This survives local uploader restarts.
optional string command_id = 11;
}

// List of files, in order of time, that are pending upload.
Expand Down
16 changes: 10 additions & 6 deletions src/bitdrift_public/protobuf/workflow/v1/workflow.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import "bitdrift_public/protobuf/matcher/v1/log_matcher.proto";
import "bitdrift_public/protobuf/state/v1/matcher.proto";
import "bitdrift_public/protobuf/state/v1/scope.proto";
import "bitdrift_public/protobuf/workflow/v1/save_field.proto";
import "bitdrift_public/protobuf/workflow/v1/workflow_command.proto";
import "google/protobuf/timestamp.proto";
import "validate/validate.proto";

Expand Down Expand Up @@ -228,16 +229,24 @@ message Workflow {
ActionFlushBuffers action_flush_buffers = 1;
ActionEmitMetric action_emit_metric = 2;
ActionEmitSankeyDiagram action_emit_sankey_diagram = 3;
ActionTakeScreenshot action_take_screenshot = 4;
ActionGenerateLog action_generate_log = 5;
ActionStartTracing action_start_tracing = 6;
ActionRunCommand action_run_command = 7;
}

reserved 4;
reserved "action_take_screenshot";

// Specifies that the current session will start trace sampling. Tracing will stop when the
// workflow run ends. The exception to this is if the run results in a flush. If this happens,
// tracing will stay on until flush streaming completes.
message ActionStartTracing {}

// Runs one locally registered or built-in command when this transition is taken.
message ActionRunCommand {
WorkflowCommandSelector command_selector = 1 [(validate.rules).message = {required: true}];
}

// Generates a new log message. This log will be injected into the workflow engine and processed
// like any other log, either by this workflow or by another workflow.
message ActionGenerateLog {
Expand Down Expand Up @@ -468,11 +477,6 @@ message Workflow {
reserved 5;
reserved "feature_flag_extracted";
}

// Emit a log containing application screenshot.
message ActionTakeScreenshot {
reserved 1;
}
}

message Execution {
Expand Down
37 changes: 37 additions & 0 deletions src/bitdrift_public/protobuf/workflow/v1/workflow_command.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// api - bitdrift's client/server API definitions
// Copyright Bitdrift, Inc. All rights reserved.
//
// Use of this source code and APIs are governed by a source available license that can be found in
// the LICENSE file or at:
// https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt

syntax = "proto3";

package bitdrift_public.protobuf.workflow.v1;

import "validate/validate.proto";

// Selects one locally registered or built-in workflow command.
message WorkflowCommandSelector {
// Built-in commands supported directly by the client workflow runtime.
message BuiltinCommand {
oneof command_type {
option (validate.required) = true;

// Captures one application screenshot using the platform's configured defaults.
TakeScreenshot take_screenshot = 1;
}

message TakeScreenshot {}
}

oneof command_selector {
option (validate.required) = true;

// An opaque customer-registered command handler identifier.
string registered_command_id = 1 [(validate.rules).string.uuid = true];

// A strongly typed command implemented by the client workflow runtime.
BuiltinCommand builtin_command = 2;
}
}
Loading