// wire-rs: encrypted protocol between Ark and host
// Copyright 2025 Dark Bio AG. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
syntax = "proto3";
package darkbio.wire;
// HostToArk represents a message sent from the host to the Ark via the USB
// connection. It embeds all possible message types to keep the protocol simple.
//
// Every message carries an id and is either a request, its id chosen by the
// host, or the host's response to a request of the Ark, echoing the Ark's id.
// To avoid id collisions, hosts allocate odd ids and Arks even ones, so a
// receiver can tell a response from a request by the parity of the id alone.
message HostToArk {
// Enveloping fields, reserved range 0x001-0x0ff
uint64 id = 1; // Request identifier, the host's own or responded to
optional Error err = 2; // Error encountered while serving the Ark's request (if any)
// Body of the message, a request of the host or its response to a request of
// the Ark. The tags are grouped by area, each area with its own range.
oneof content {
// Special factory message
OnboardingRequest onboard = 0x100; // Installs the signed device attestation at manufacturing
// System messages, reserved range 0x101-0x200
DeviceInfoRequest device_info = 0x101; // Fetches the hardware and firmware versions
CloudSyncStartRequest cloud_sync_start = 0x102; // Starts a cloud sync with the attested cloud keys
CloudSyncFinishRequest cloud_sync_finish = 0x103; // Finishes a cloud sync with the signed server time
GenuinityProofRequest genuinity_proof = 0x104; // Requests a proof of the device's genuinity
// Firmware update messages, reserved range 0x201-0x300
FirmwareUpdatePrepRequest firmware_update_prep = 0x201; // Prepares an update, aborting any in progress
FirmwareUpdateInitRequest firmware_update_init = 0x202; // Initiates a prepared update with the sealed firmware key
FirmwareUpdateUploadRequest firmware_update_upload = 0x203; // Appends a chunk of the firmware archive
FirmwareUpdateVerifyRequest firmware_update_verify = 0x204; // Decrypts and verifies the uploaded firmware
FirmwareUpdateInstallRequest firmware_update_install = 0x205; // Installs the verified firmware and reboots
// Pairing messages, reserved range 0x301-0x400
PairingAuthRequest pairing_auth = 0x301; // Asks the Ark to authorize a pairing rendezvous
PairingSetAppIdentityRequest pairing_set_app_id = 0x302; // Injects the companion app's identity, relayed by the cloud
PairingSetAppStorageRequest pairing_set_app_storage = 0x303; // Injects the companion app's storage key material
PairingAckArkStorageRequest pairing_ack_ark_storage = 0x304; // Confirms the app received the Ark's key material
PairingAcceptanceRequest pairing_accept = 0x305; // Waits for the user to accept the pairing
PairingCompletionRequest pairing_complete = 0x306; // Waits for the Ark to finish pairing maintenance
// Relay messages, reserved range 0x401-0x500
RelayJoinRequest relay_join = 0x401; // Asks the Ark to authorize joining the app relay
RelayAppToArkRequest relay_req = 0x402; // Opaque request from the companion app to the Ark
RelayAppToArkResponse relay_res = 0x403; // Opaque response from the companion app to an Ark request
// Operational messages, reserved range 0x501-0x600
UnlockRequest unlock = 0x501; // Starts the unlock, confirmed through the app
ExecutionUploadStartRequest exec_upload_start = 0x502; // Begins a chunked upload of an app to execute
ExecutionUploadChunkRequest exec_upload_chunk = 0x503; // Appends a chunk to a pending app upload
ExecutionScheduleRequest exec_sched = 0x504; // Runs an uploaded app, confirmed through the app
ExecutionStatusRequest exec_status = 0x505; // Checks on a running app
ExecutionCancelRequest exec_cancel = 0x506; // Cancels an app run or a pending upload
// Slot messages, reserved range 0x601-0x700
SlotListRequest slot_list = 0x601; // Lists the state of every data slot
SlotRepairRequest slot_repair = 0x602; // Resets a slot to empty whatever its state
SlotDeleteRequest slot_delete = 0x603; // Removes the contents of a filled slot
SlotIdentifyRequest slot_identify = 0x604; // Asks the Ark to identify a file from its first chunk
SlotUploadStartRequest slot_upload_start = 0x605; // Starts uploading a file into a slot
SlotUploadChunkRequest slot_upload_chunk = 0x606; // Appends a chunk to a pending slot upload
SlotUploadCancelRequest slot_upload_cancel = 0x607; // Aborts a pending slot upload
SlotUploadProcessRequest slot_upload_process = 0x608; // Marks an upload complete and polls its processing
// Dataset messages, reserved range 0x701-0x800
DatasetPathsRequest dataset_paths = 0x701; // Maps every path an app can read, from the dataset view
// Unreleased messages served by development firmware only, carried opaquely
// so the public protocol is untouched while they are still under development.
// Their schema is private and production Arks refuse the envelope.
bytes develop = 0x1000;
}
}
// ArkToHost represents a message sent from the Ark to the host via the USB
// connection. It embeds all possible message types to keep the protocol simple.
//
// Every message carries an id and is either a request, its id chosen by the
// Ark, or the Ark's response to a request of the host, echoing the host's id.
// To avoid id collisions, hosts allocate odd ids and Arks even ones, so a
// receiver can tell a response from a request by the parity of the id alone.
message ArkToHost {
// Enveloping fields, reserved range 0x001-0x0ff
uint64 id = 1; // Request identifier, responded to or the Ark's own
optional Error err = 2; // Error encountered while serving the host's request (if any)
// Body of the message, a response of the Ark to a request of the host or a
// request of its own. The tags are grouped by area, each area with its own range.
oneof content {
// Special factory message
OnboardingResponse onboard = 0x100; // Acknowledges the onboarding
// System messages, reserved range 0x101-0x200
DeviceInfoResponse device_info = 0x101; // Hardware and firmware versions of the Ark
CloudSyncStartResponse cloud_sync_start = 0x102; // Challenge for the cloud to sign along its time
CloudSyncFinishResponse cloud_sync_finish = 0x103; // Timestamp the Ark accepted from the cloud
GenuinityProofResponse genuinity_proof = 0x104; // Encrypted proof of the Ark's genuinity for the cloud
// Firmware update messages, reserved range 0x201-0x300
FirmwareUpdatePrepResponse firmware_update_prep = 0x201; // Ephemeral key to receive the firmware key with, sealed for the cloud
FirmwareUpdateInitResponse firmware_update_init = 0x202; // Acknowledges the initiated update
FirmwareUpdateUploadResponse firmware_update_upload = 0x203; // Acknowledges the appended firmware chunk
FirmwareUpdateVerifyResponse firmware_update_verify = 0x204; // Acknowledges the verified firmware
FirmwareUpdateInstallResponse firmware_update_install = 0x205; // Acknowledges the installed firmware
// Pairing messages, reserved range 0x301-0x400
PairingAuthResponse pairing_auth = 0x301; // Signed authorization for the cloud to open a rendezvous
PairingSetAppIdentityResponse pairing_set_app_id = 0x302; // Acknowledges the accepted app identity
PairingSetAppStorageResponse pairing_set_app_storage = 0x303; // Ark device infos and key material, sealed for the app
PairingAckArkStorageResponse pairing_ack_ark_storage = 0x304; // Acknowledges the app's receipt of the Ark's keys
PairingAcceptanceResponse pairing_accept = 0x305; // Signed confirmation that the user accepted the pairing
PairingCompletionResponse pairing_complete = 0x306; // Signed confirmation that the Ark finished pairing
// Relay messages, reserved range 0x401-0x500
RelayJoinResponse relay_join = 0x401; // Signed authorization for the cloud to join the relay
RelayArkToAppRequest relay_req = 0x402; // Opaque request from the Ark to the companion app
RelayArkToAppResponse relay_res = 0x403; // Opaque response from the Ark to an app request
RelayAppToArkFailure relay_fail = 0x404; // Protocol violation found in an app response, for debugging
// Operational messages, reserved range 0x501-0x600
UnlockResponse unlock = 0x501; // Acknowledges the completed unlock
ExecutionUploadStartResponse exec_upload_start = 0x502; // Task id for the chunk, schedule and cancel messages
ExecutionUploadChunkResponse exec_upload_chunk = 0x503; // Acknowledges the appended app chunk
ExecutionScheduleResponse exec_sched = 0x504; // Acknowledges the authorized and started execution
ExecutionStatusResponse exec_status = 0x505; // Whether the app still runs, with its result once done
ExecutionCancelResponse exec_cancel = 0x506; // Acknowledges the cancelled run or upload
// Slot messages, reserved range 0x601-0x700
SlotListResponse slot_list = 0x601; // Current state of every data slot
SlotRepairResponse slot_repair = 0x602; // Acknowledges the reset slot
SlotDeleteResponse slot_delete = 0x603; // Acknowledges the deleted slot
SlotIdentifyResponse slot_identify = 0x604; // Identification of the file's first chunk
SlotUploadStartResponse slot_upload_start = 0x605; // Session id of the approved upload
SlotUploadChunkResponse slot_upload_chunk = 0x606; // Acknowledges the appended slot chunk
SlotUploadCancelResponse slot_upload_cancel = 0x607; // Acknowledges the aborted upload
SlotUploadProcessResponse slot_upload_process = 0x608; // Processing progress of the completed upload
// Dataset messages, reserved range 0x701-0x800
DatasetPathsResponse dataset_paths = 0x701; // Every path an app can read, with its description, format and examples
// Unreleased messages emitted by development firmware only, in response to
// a develop request, carried opaquely so the public protocol is untouched
// while they are still under development. Their schema is private.
bytes develop = 0x1000;
}
}
// Error is sent along a response to a failed request.
//
// Codes 0x00 through 0xff (inclusive) are reserved for protocol-wide errors.
// Codes 0x100 and above are defined by the request type and may be reused
// with different meanings for different requests. The message text is human,
// readable error, not a stable code.
message Error {
uint64 code = 1; // Error code for programmatic interpretation
string msg = 2; // Error message for user interfacing
}
// ReservedErrors names the assigned protocol-wide errors in the reserved range
// 0x00 to 0xff (inclusive). No code in this range may be assigned a request
// specific meaning. Assigned codes must not be repurposed.
enum ReservedErrors {
// A failure without a standardized reason. Zero does not indicate success;
// the presence of an Error in the response indicates failure.
RESERVED_ERRORS_UNSPECIFIED = 0;
// The request's responder was released without providing an application reply.
RESERVED_ERRORS_UNANSWERED = 1;
// The peer does not know this request. Emitted by the protocol layer itself
// when a request's content is not in its schema.
RESERVED_ERRORS_UNKNOWN = 2;
// The peer knows this request but never serves it in this build or role,
// firmware updates on an emulator or develop envelopes on production.
RESERVED_ERRORS_UNSUPPORTED = 3;
// The peer serves this request but not in its current state, before cloud
// sync or pairing. It may once the state changes.
RESERVED_ERRORS_UNAVAILABLE = 4;
// The peer serves this request but the owner refused the approval it asked
// for on the phone. The owner's choice, not a failure.
RESERVED_ERRORS_UNAUTHORIZED = 5;
// The peer serves this request but the approval it asked for did not arrive
// before its window ran out, on the phone or at the button.
RESERVED_ERRORS_UNCONFIRMED = 6;
}
// OnboardingRequest is a vendor utility to onboard an Ark. Currently it contains
// the signed device genuinity attestation (certificate).
//
// Note, as this method is only used during initial device setup, there is no API
// compatibility guarantee, it will evolve with the factory tooling.
message OnboardingRequest {
bytes device_attestation = 1; // Signed device genuinity attestation (CWT) to install
}
// OnboardingResponse is the acknowledgement of the onboarding.
message OnboardingResponse {
}
// DeviceInfoRequest is sent by the host to fetch the Ark's device stats.
message DeviceInfoRequest {
}
// DeviceInfoResponse returns various hardware and software version information.
message DeviceInfoResponse {
uint32 version_id = 1; // Ark device version (defines the major features)
string version_str = 2; // Ark device version label (as known by the device)
uint32 revision_id = 3; // Ark device revision (defines the minor differences)
string revision_str = 4; // Ark device revision label (as known by the device)
reserved 5; // Carried the Ark's hex identity before @darkbio/crypto, derived since
reserved 6; // Carried the Ark's pubkey before the encrypted wire, in handshake now
string firmware_version = 7; // Current firmware version (X.Y.Z-commit)
uint64 firmware_publish = 8; // Current firmware publish unix timestamp
bool cloud_synced = 9; // Whether a cloud identity was accepted since boot
uint64 cloud_clock = 10; // Current device clock unix timestamp, set by the cloud sync
bool paired = 11; // Whether the Ark is paired with a companion app (user data initialized)
bool unlocked = 12; // Whether the user data storage is open (false if unpaired)
}
// CloudSyncStartRequest requests the device to start a synchronization procedure
// against the cloud servers to establish the current time as well as the currently
// active cloud identity.
message CloudSyncStartRequest {
bytes signer = 1; // Post-quantum CWT attestation for the server signing (xDSA) key
bytes crypto = 2; // Post-quantum CWT attestation for the server encryption (xHPKE) key
}
// CloudSyncStartResponse is an initiation of a cloud sync from the device, authed
// to the requested cloud identity.
message CloudSyncStartResponse {
bytes challenge = 1; // Random nonce to avoid malicious host machines setting bad times
}
// CloudSyncFinishRequest is the completion of a previously initiated cloud sync
// procedure, this time being signed by a single identity currently used by the
// cloud.
message CloudSyncFinishRequest {
uint64 unixmilli = 1; // Unix timestamp from the server in milliseconds
bytes signature = 2; // SignAt[Cloud]["cloudsync-v1"][unixmilli/1000](CBOR(challenge))
}
// CloudSyncFinishResponse is the acknowledgement whether the device accepted the
// cloud sync from the server or rejected for some reason.
message CloudSyncFinishResponse {
uint64 accepted = 1; // Timestamp that was accepted and set
}
// GenuinityProofRequest requests the device to generate a cryptographic proof of
// its own authenticity.
message GenuinityProofRequest {
}
// GenuinityProofResponse is the device genuinity proof, an encrypted signature
// of the device.
message GenuinityProofResponse {
bytes proof = 1; // Seal[Ark->Cloud]["genuinity-v1"][null](null)
}
// FirmwareUpdatePrepRequest prepares a firmware update procedure. If any previous
// update procedure was in progress, it is aborted.
message FirmwareUpdatePrepRequest {
string version = 1; // Version string to update to
bytes sha256 = 2; // SHA256 hash of the (encrypted) firmware archive
uint64 bytes = 3; // Number of bytes (progress purposes, ignored otherwise)
}
// FirmwareUpdatePrepResponse confirms whether a new firmware update process was
// started, or if the request was rejected and why.
//
// If it was accepted, a new ephemeral encryption identity is generated by the Ark
// to receive the firmware access key to; and sent along with the firmware infos.
message FirmwareUpdatePrepResponse {
bytes auth = 1; // Seal[Ark->Cloud]["firmware-v1"][[version, sha256]](temp-key)
}
// FirmwareUpdateInitRequest initiates a previously prepared firmware update
// procedure by providing the authenticated and encrypted firmware key.
//
// Note, if the initiation is rejected, the entire update process is torn down.
message FirmwareUpdateInitRequest {
bytes access = 1; // Seal[Cloud->temp-key]["firmware-v1"][[version, sha256]](sym-key)
}
// FirmwareUpdateInitResponse confirms whether a new firmware update process
// was started, or if the request was rejected and why.
//
// Note, if the init is rejected, the entire update process is torn down.
message FirmwareUpdateInitResponse {
}
// FirmwareUpdateUploadRequest requests appending a new chunk of data to the
// currently pending firmware upload process.
message FirmwareUpdateUploadRequest {
bytes chunk = 1; // Chunk of firmware blob to append (reasonably capped)
}
// FirmwareUpdateUploadResponse is the response whether the requested chunk was
// accepted or rejected.
//
// Note, if the upload is rejected, the entire update process is torn down.
message FirmwareUpdateUploadResponse {
}
// FirmwareUpdateVerifyRequest requests decrypting the uploaded firmware and
// verifying its contents, preparing for the last step of actually installing
// the firmware update.
message FirmwareUpdateVerifyRequest {
}
// FirmwareUpdateVerifyResponse is the response whether the firmware just uploaded
// passed all verifications and is ready for application.
//
// Note, if the verification is rejected, the entire update process is torn down.
message FirmwareUpdateVerifyResponse {
}
// FirmwareUpdateInstallRequest requests the currently pending (but already
// verified) firmware to be applied to disk. This message will cause the device
// to reboot if applied successfully.
message FirmwareUpdateInstallRequest {
}
// FirmwareUpdateInstallResponse is the response whether the firmware was applied
// successfully or not.
message FirmwareUpdateInstallResponse {
}
// PairingAuthRequest requests the initiation of a pairing.
message PairingAuthRequest {
}
// PairingAuthResponse responds whether the device is in a state compatible with
// pairing (i.e. reset) and if so, it signs an authorization for the server to open
// a new rendezvous point; containing the xHPKE public key to use for encrypting
// messages to this Ark after pairing.
message PairingAuthResponse {
bytes auth = 1; // Seal[Ark->Cloud]["pairing-v1"][null](pair-key)
bytes fprint = 2; // Fingerprint of the pair-key to transmit to the app out-of-protocol
}
// PairingSetAppIdentityRequest injects the companion app's identity, relayed
// by the cloud.
message PairingSetAppIdentityRequest {
bytes identity = 1; // Seal[Cloud->App]["pairing-v1:identity"][[ark_signer_id, ark_crypto_id]]([app_signer, app_crypto])
}
// PairingSetAppIdentityResponse confirms whether the remote identity was
// accepted by the Ark or not.
message PairingSetAppIdentityResponse {
}
// PairingSetAppStorageRequest injects the app's storage key material into the
// pairing flow.
message PairingSetAppStorageRequest {
bytes app_key = 1; // Seal[App->Ark]["pairing-v1:storage"][[ark_signer_id, ark_crypto_id, app_signer_id, app_crypto_id]]([app_keymat])
}
// PairingSetAppStorageResponse confirms whether the remote storage material
// was accepted, and if so, bundles the ark device infos and ark key material.
message PairingSetAppStorageResponse {
bytes ark_keys = 1; // Seal[Ark->App]["pairing-v1:storage"][[ark_signer_id, ark_crypto_id, app_signer_id, app_crypto_id, app_keymat]]([hw_ver, hw_rev, fw_ver, fw_pub, ark_keymat])
}
// PairingAckArkStorageRequest confirms from the app that the Ark's key material
// was received correctly.
message PairingAckArkStorageRequest{
bytes app_ack = 1; // Seal[App->Ark]["pairing-v1:storage"][[ark_signer_id, ark_crypto_id, app_signer_id, app_crypto_id, ark_keymat]](null)
}
// PairingAckArkStorageResponse confirms that the key ack was accepted.
message PairingAckArkStorageResponse{
}
// PairingAcceptanceRequest is a blocking poller to wait until the user accepts
// a pairing request or it times out.
message PairingAcceptanceRequest {
}
// PairingAcceptanceResponse returns whether the user accepted the pairing or
// if it timed out. At this point, the device still needs to format itself.
message PairingAcceptanceResponse {
bytes confirm = 1; //Seal[Ark->Cloud]["pairing-v1:accept"][[ark_signer_id, ark_crypto_id, app_signer_id, app_crypto_id]](null)
}
// PairingCompletionRequest is a blocking poller to wait until the device finishes
// any pairing maintenance operation (e.g. encrypting itself).
message PairingCompletionRequest {
}
// PairingCompletionResponse returns whether the device finished preparing for
// live operation.
message PairingCompletionResponse {
bytes confirm = 1; // Seal[Ark->Cloud]["pairing-v1:complete"][[ark_signer_id, ark_crypto_id, app_signer_id, app_crypto_id]](null)
}
// RelayJoinRequest requests authorization to join the communication relay with
// the companion app.
message RelayJoinRequest {
}
// RelayJoinResponse responds whether the device is in a state compatible with
// relaying (i.e. paired) and if so, it signs an authorization for the server
// to join the rendezvous point.
message RelayJoinResponse {
bytes auth = 1; // Seal[Ark->Cloud]["relaying-v1"][null](null)
}
// RelayAppToArkRequest is an opaque request from the companion app that the Ark may
// respond to, or may flat out reject.
message RelayAppToArkRequest {
uint64 id = 1; // Application layer request ID from the app
bytes req = 2; // Seal[App->Ark]["relaying-v1:request"][id]([method, [params...]]))
}
// RelayArkToAppResponse is an opaque response from the Ark to the companion app to an
// opaque request.
message RelayArkToAppResponse {
uint64 id = 1; // Application layer request ID from the app being responding to
bytes res = 2; // Seal[Ark->App]["relaying-v1:response"][id]([result, [err_code, err_str]])
}
// RelayAppToArkFailure is returned if a low level protocol violation is detected
// when an app-to-ark response was processed.
//
// This is not an actionable message, rather it's just a way to expose a protocol
// failure / violation to the calling app for debugging purposes.
message RelayAppToArkFailure {
string error = 1; // Reason for rejecting the response at the protocol level
}
// RelayArkToAppRequest is an opaque request from the Ark to the companion app, which
// will generally be sent as an interim response to some other request, requiring
// authorization from the app side.
message RelayArkToAppRequest {
uint64 id = 1; // Application layer request ID from the ark
bytes req = 2; // Seal[Ark->App]["relaying-v1:request"][id]([method, [params...]])
}
// RelayAppToArkResponse is an opaque response from the companion app to an opaque
// Ark request. The ark will respond with the deferred response to the original
// request.
message RelayAppToArkResponse {
uint64 id = 1; // Application layer request ID from the ark being responding to
bytes res = 2; // Seal[App->Ark]["relaying-v1:response"][id]([result, [err_code, err_str]])
}
// UnlockRequest requests the device to start the unlock procedure. This request
// is async, potentially returning a response only after confirming with the app.
//
// It will trigger sending a RelayArkToAppRequest with the request content:
// - method: "unlock"
// - params: []
//
// The request expects a RelayAppToArkResponse with the response content:
//
// If approved:
// - result = key: [u8; 32] // Shared secret from the pairing protocol
// - err_code: 0
// - err_str: ""
//
// If denied:
// - result = key = [0u8; 32] // All zeroes (signals a denial)
// - err_code: 0 // No error, deny is valid user choice
// - err_str: "" // No error, deny is valid user choice
//
// where:
// - key: Symmetric key for accessing the storage partition
//
// Note, relayed messages are encrypted and authenticated on the timestamp and
// request/response id, so there's no need for further complications.
message UnlockRequest{
}
// UnlockResponse contains whether the unlock was successfully executed.
message UnlockResponse{
}
// ExecutionUploadStartRequest begins a chunked upload of a WASM binary to
// execute. The declared size is used to pre-allocate the receive buffer and
// to reject oversized uploads early; the actual bytes are sent via subsequent
// ExecutionUploadChunkRequest messages.
message ExecutionUploadStartRequest{
uint64 bytes = 1; // Total binary size in bytes
}
// ExecutionUploadStartResponse contains the task id to use for subsequent
// chunk, schedule and cancel messages.
message ExecutionUploadStartResponse{
uint64 taskid = 1; // Task id to stream chunks into
}
// ExecutionUploadChunkRequest appends a chunk of data to a pending upload.
// Chunks must be appended in order and must not overrun the declared size.
message ExecutionUploadChunkRequest{
uint64 taskid = 1; // Task id to append to
bytes chunk = 2; // Data chunk to append (reasonably capped)
}
// ExecutionUploadChunkResponse is an empty ack of the chunk upload request.
message ExecutionUploadChunkResponse{
}
// ExecutionScheduleRequest finalizes an upload and requests the device to
// execute the uploaded 3rd party app. The upload must have been completed
// (i.e. the sum of chunk sizes matches the declared size).
//
// This request is async, potentially returning a response only after confirming
// with the app.
//
// It will trigger sending a RelayArkToAppRequest with the request content:
// - method: "execute"
// - params: [task: string]
//
// The request expects a RelayAppToArkResponse with the response content:
//
// If approved:
// - result = approval = true // CBOR boolean
// - err_code: 0
// - err_str: ""
//
// If denied:
// - result = approval = false // CBOR boolean
// - err_code: 0 // No error, deny is valid user choice
// - err_str: "" // No error, deny is valid user choice
//
// where:
// - approval: Whether the user approved or denied the execution request
//
// Note, relayed messages are encrypted and authenticated on the timestamp and
// request/response id, so there's no need for further complications.
message ExecutionScheduleRequest{
uint64 taskid = 1; // Task id returned by ExecutionUploadStartResponse
}
// ExecutionScheduleResponse acks that the execution was authorized and the
// task is now running. The host already holds the task id from the preceding
// ExecutionUploadStartResponse.
message ExecutionScheduleResponse{
}
// ExecutionCancelRequest cancels a previously started 3rd party app run or
// an in-progress upload.
message ExecutionCancelRequest{
uint64 taskid = 1; // Task id to cancel
}
// ExecutionCancelResponse contains the data gathered during an app's execution.
message ExecutionCancelResponse{
}
// ExecutionStatusRequest checks the execution status of a previously started
// 3rd party app run.
message ExecutionStatusRequest{
uint64 taskid = 1; // Pending execution ID to check for updates
}
// ExecutionResultResponse contains the data gathered during an app's execution.
message ExecutionResultResponse{
string app_name = 2; // Name of the executed app
string app_version = 3; // Version of the executed app
bool success = 4; // Whether the task finished successfully
bytes stdout = 5; // Raw standard output of the app
bytes stderr = 6; // Raw standard error the app (only in develop mode)
}
// ExecutionStatusResponse contains the status of a started 3rd party app
// execution.
message ExecutionStatusResponse{
bool pending = 1; // Whether the app is still running
optional ExecutionResultResponse result = 2; // The result of the execution
}
// SlotKind identifies a slot on the device. Each value corresponds to a unique
// data type that the device can store and manage.
enum SlotKind {
SLOT_UNSPECIFIED = 0; // Never sent, an unset kind
SLOT_REFERENCE_GENOME = 1; // Human reference genome assembly
SLOT_GENE_ANNOTATIONS = 2; // Gene-to-coordinate mapping database
SLOT_SNP_INDEL_CALLS = 3; // User's SNP/indel variant calls
SLOT_VARIANT_CATALOG = 4; // Variant catalog (rsID-to-position), from dbSNP
}
// SlotOrigin describes the nature of the data in a slot, determining what
// actions are available to the user for filling it.
enum SlotOrigin {
ORIGIN_UNSPECIFIED = 0; // Never sent, an unset origin
ORIGIN_PERSONAL = 1; // Unique to the user, uploaded by them
ORIGIN_REFERENCE = 2; // Standard reference data, downloaded from public sources
}
// SlotState describes whether a slot holds data and whether that data is sound.
enum SlotState {
STATE_UNSPECIFIED = 0; // Never sent, an unset state
STATE_EMPTY = 1; // Nothing stored
STATE_FILLED = 2; // Data present and healthy
STATE_DAMAGED = 3; // Files exist but the metadata is missing, corrupt or outdated
}
// SlotConfidence indicates how confident the device is in its identification
// of a file, based on content, filename and size.
enum SlotConfidence {
CONFIDENCE_UNSPECIFIED = 0; // Never sent, an unset confidence
CONFIDENCE_LOW = 1; // Filename/extension only, no content confirmation
CONFIDENCE_MID = 2; // Format detected but slot type inferred from size/filename
CONFIDENCE_HIGH = 3; // Magic bytes match and format-specific content confirmed
}
// SlotDownload describes the public download the device advertises for a
// reference slot, so a host can fetch it and stream it back in.
message SlotDownload {
string url = 1; // Public download URL
uint64 bytes = 2; // Download size in bytes
string sha256 = 3; // Download SHA256 checksum
}
// SlotStatus describes the current state of a single slot on the device. The
// data fields are generic so a host renders a kind it has never seen.
message SlotStatus {
SlotKind kind = 1; // Slot type
string name = 2; // Human-readable slot name
string desc = 3; // Owner-facing description of the data this slot holds
string format = 4; // The file that fills this slot, its required shape and what is refused
SlotOrigin origin = 5; // Nature of the data (personal, reference)
SlotState state = 6; // Whether the slot is empty, filled or damaged
string damage = 7; // Why the slot is damaged, empty otherwise
repeated SlotKind deps = 8; // Slots that must be filled before this one is actionable
uint64 bytes = 9; // Bytes on disk for this slot (0 if empty)
string build = 10; // Reference assembly the data is keyed to (e.g. "GRCh38.p14")
string version = 11; // The dataset's own release, if it has one (e.g. dbSNP "157")
SlotDownload download = 12; // Advertised public download, absent if none
}
// SlotListRequest requests the state of all slots on the device.
message SlotListRequest {
}
// SlotListResponse contains the current state of every slot.
message SlotListResponse {
repeated SlotStatus slots = 1; // State of every slot, one entry per slot kind
}
// SlotRepairRequest resets a slot to empty regardless of its current state.
// Unlike SlotDelete (which requires the slot to be filled), repair is a stateless
// force cleanup that removes any leftover metadata and/or files on disk. It is
// intended for recovering from corruption or half-written state after crashes.
message SlotRepairRequest {
SlotKind slot = 1; // Slot to repair (reset to empty)
}
// SlotRepairResponse is an empty ack of the repair request.
message SlotRepairResponse {
}
// SlotDeleteRequest removes the contents of a filled slot. The slot must be
// in a healthy, filled state; corrupted or half-written slots must be cleaned
// up via SlotRepair instead.
message SlotDeleteRequest {
SlotKind slot = 1; // Slot to delete
}
// SlotDeleteResponse is an empty ack of the delete request.
message SlotDeleteResponse {
}
// SlotIdentifyRequest sends an ephemeral file chunk to the Ark and asks it to
// identify the file. Its purpose is to filter potentially huge files (e.g. a
// 30GB compressed whole genome sequencing) before uploading them, and to
// answer what a file is without uploading it at all.
message SlotIdentifyRequest {
string name = 1; // File name to guess the contents of
uint64 size = 2; // File size to guess the contents of
bytes chunk = 3; // First chunk of the file to guess the contents of
repeated SlotKind kinds = 4; // Possible slots to interpret as (empty == any)
}
// SlotIdentifyResponse contains the identification based on the chunk shared
// in the request.
message SlotIdentifyResponse {
SlotKind kind = 1; // Identified slot type to use during upload
SlotConfidence conf = 2; // Identification confidence level
string summary = 3; // Short summary of the identified data
string details = 4; // Detailed description of the identified data
string rejection = 5; // Reason why the file is rejected, empty otherwise
}
// SlotUploadStartRequest requests uploading a file into a slot of the given
// kind (e.g. a whole genome variant call file).
message SlotUploadStartRequest {
SlotKind kind = 1; // Slot type requesting to upload
string name = 2; // File name to guess the contents of
uint64 size = 3; // File size to guess the contents of
bytes chunk = 4; // First chunk of the file to guess the contents of
}
// SlotUploadStartResponse contains a unique session id for an approved upload.
message SlotUploadStartResponse {
uint64 session = 1; // Session id for concurrent uploads (not recommended)
}
// SlotUploadChunkRequest contains a new chunk of data to append to a pending
// upload session.
message SlotUploadChunkRequest {
uint64 session = 1; // Session id into which to append a new chunk
bytes chunk = 2; // Data chunk to append (reasonably capped)
}
// SlotUploadChunkResponse is an empty ack of the chunk upload request.
message SlotUploadChunkResponse {
}
// SlotUploadCancelRequest contains an upload session id to abort.
message SlotUploadCancelRequest {
uint64 session = 1; // Session id to cancel
}
// SlotUploadCancelResponse is an empty ack of the cancellation request.
message SlotUploadCancelResponse {
}
// SlotPhase names one step of a slot's processing pipeline.
message SlotPhase {
string name = 1; // Short label for the phase
string desc = 2; // Description of what the phase does
}
// SlotUploadProcessRequest marks an upload session ready for processing and
// requests a progress report to be sent back. May be called multiple times.
message SlotUploadProcessRequest {
uint64 session = 1; // Session id to mark as completed
}
// SlotUploadProcessResponse acks the completion of a slot upload and also
// contains the current processing progress.
message SlotUploadProcessResponse {
uint64 proc_start = 1; // Unix timestamp when data processing started
repeated SlotPhase phases = 2; // Every phase of the pipeline, in order
uint64 phase_in = 3; // Current phase (1-indexed)
uint64 phase_start = 4; // Unix timestamp when the current phase started
uint64 phase_progress = 5; // Approximate progress for this phase [0-10000]
string failure = 6; // Failure reason if processing failed, empty otherwise
}
// DatasetPathsRequest requests the map of every path an app can read, the
// dataset view the device derives from its slots, lenses included.
message DatasetPathsRequest {
}
// DatasetPathsResponse maps every path an app can read, available or not, in
// tree order. It describes the tree only and never carries a value from the
// owner's data.
message DatasetPathsResponse {
repeated DatasetPath paths = 1; // Every path pattern, in tree order
}
// DatasetPath describes one path pattern under the data root. A segment in angle
// brackets is a placeholder, described by the directory entry it names. The path
// is the entry's stable key.
message DatasetPath {
string path = 1; // Path as a manifest names it
bool directory = 2; // Directory or file
bool grantable = 3; // Whether a manifest may name it
bool available = 4; // Whether the data this path needs is on the Ark now
string desc = 5; // What it holds, when it is absent and when it fails
string format = 6; // Exact file content, or what a directory lists
repeated string examples = 7; // Complete example values, most typical first
}