From 16f0e67d02652ecd4f8daa953aa06ca19a63b2c1 Mon Sep 17 00:00:00 2001 From: hdbg Date: Fri, 3 Apr 2026 19:08:19 +0200 Subject: [PATCH] refactor(proto): scope client and user-agent schemas and extract shared types --- protobufs/client.proto | 57 ++++----------------- protobufs/client/auth.proto | 43 ++++++++++++++++ protobufs/client/evm.proto | 19 +++++++ protobufs/client/vault.proto | 18 +++++++ protobufs/evm.proto | 71 ++------------------------ protobufs/shared/client.proto | 9 ++++ protobufs/shared/evm.proto | 68 ++++++++++++++++++++++++ protobufs/shared/vault.proto | 11 ++++ protobufs/user_agent/sdk_client.proto | 6 +-- protobufs/user_agent/vault/vault.proto | 11 +--- 10 files changed, 186 insertions(+), 127 deletions(-) create mode 100644 protobufs/client/auth.proto create mode 100644 protobufs/client/evm.proto create mode 100644 protobufs/client/vault.proto create mode 100644 protobufs/shared/client.proto create mode 100644 protobufs/shared/evm.proto create mode 100644 protobufs/shared/vault.proto diff --git a/protobufs/client.proto b/protobufs/client.proto index 83d25cf..e1b346c 100644 --- a/protobufs/client.proto +++ b/protobufs/client.proto @@ -2,63 +2,24 @@ syntax = "proto3"; package arbiter.client; -import "evm.proto"; -import "google/protobuf/empty.proto"; - -message ClientInfo { - string name = 1; - optional string description = 2; - optional string version = 3; -} - -message AuthChallengeRequest { - bytes pubkey = 1; - ClientInfo client_info = 2; -} - -message AuthChallenge { - bytes pubkey = 1; - int32 nonce = 2; -} - -message AuthChallengeSolution { - bytes signature = 1; -} - -enum AuthResult { - AUTH_RESULT_UNSPECIFIED = 0; - AUTH_RESULT_SUCCESS = 1; - AUTH_RESULT_INVALID_KEY = 2; - AUTH_RESULT_INVALID_SIGNATURE = 3; - AUTH_RESULT_APPROVAL_DENIED = 4; - AUTH_RESULT_NO_USER_AGENTS_ONLINE = 5; - AUTH_RESULT_INTERNAL = 6; -} - -enum VaultState { - VAULT_STATE_UNSPECIFIED = 0; - VAULT_STATE_UNBOOTSTRAPPED = 1; - VAULT_STATE_SEALED = 2; - VAULT_STATE_UNSEALED = 3; - VAULT_STATE_ERROR = 4; -} +import "client/auth.proto"; +import "client/evm.proto"; +import "client/vault.proto"; message ClientRequest { int32 request_id = 4; oneof payload { - AuthChallengeRequest auth_challenge_request = 1; - AuthChallengeSolution auth_challenge_solution = 2; - google.protobuf.Empty query_vault_state = 3; + auth.Request auth = 1; + vault.Request vault = 2; + evm.Request evm = 3; } } message ClientResponse { optional int32 request_id = 7; oneof payload { - AuthChallenge auth_challenge = 1; - AuthResult auth_result = 2; - arbiter.evm.EvmSignTransactionResponse evm_sign_transaction = 3; - arbiter.evm.EvmAnalyzeTransactionResponse evm_analyze_transaction = 4; - VaultState vault_state = 6; + auth.Response auth = 1; + vault.Response vault = 2; + evm.Response evm = 3; } } diff --git a/protobufs/client/auth.proto b/protobufs/client/auth.proto new file mode 100644 index 0000000..f3d7d2d --- /dev/null +++ b/protobufs/client/auth.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; + +package arbiter.client.auth; + +import "shared/client.proto"; + +message AuthChallengeRequest { + bytes pubkey = 1; + arbiter.shared.ClientInfo client_info = 2; +} + +message AuthChallenge { + bytes pubkey = 1; + int32 nonce = 2; +} + +message AuthChallengeSolution { + bytes signature = 1; +} + +enum AuthResult { + AUTH_RESULT_UNSPECIFIED = 0; + AUTH_RESULT_SUCCESS = 1; + AUTH_RESULT_INVALID_KEY = 2; + AUTH_RESULT_INVALID_SIGNATURE = 3; + AUTH_RESULT_APPROVAL_DENIED = 4; + AUTH_RESULT_NO_USER_AGENTS_ONLINE = 5; + AUTH_RESULT_INTERNAL = 6; +} + +message Request { + oneof payload { + AuthChallengeRequest challenge_request = 1; + AuthChallengeSolution challenge_solution = 2; + } +} + +message Response { + oneof payload { + AuthChallenge challenge = 1; + AuthResult result = 2; + } +} diff --git a/protobufs/client/evm.proto b/protobufs/client/evm.proto new file mode 100644 index 0000000..ded097a --- /dev/null +++ b/protobufs/client/evm.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package arbiter.client.evm; + +import "evm.proto"; + +message Request { + oneof payload { + arbiter.evm.EvmSignTransactionRequest sign_transaction = 1; + arbiter.evm.EvmAnalyzeTransactionRequest analyze_transaction = 2; + } +} + +message Response { + oneof payload { + arbiter.evm.EvmSignTransactionResponse sign_transaction = 1; + arbiter.evm.EvmAnalyzeTransactionResponse analyze_transaction = 2; + } +} diff --git a/protobufs/client/vault.proto b/protobufs/client/vault.proto new file mode 100644 index 0000000..d9165b1 --- /dev/null +++ b/protobufs/client/vault.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package arbiter.client.vault; + +import "google/protobuf/empty.proto"; +import "shared/vault.proto"; + +message Request { + oneof payload { + google.protobuf.Empty query_state = 1; + } +} + +message Response { + oneof payload { + arbiter.shared.VaultState state = 1; + } +} diff --git a/protobufs/evm.proto b/protobufs/evm.proto index f20df52..4f7f910 100644 --- a/protobufs/evm.proto +++ b/protobufs/evm.proto @@ -4,6 +4,7 @@ package arbiter.evm; import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; +import "shared/evm.proto"; enum EvmError { EVM_ERROR_UNSPECIFIED = 0; @@ -74,70 +75,6 @@ message SpecificGrant { } } -message EtherTransferMeaning { - bytes to = 1; // 20-byte Ethereum address - bytes value = 2; // U256 as big-endian bytes -} - -message TokenInfo { - string symbol = 1; - bytes address = 2; // 20-byte Ethereum address - uint64 chain_id = 3; -} - -// Mirror of token_transfers::Meaning -message TokenTransferMeaning { - TokenInfo token = 1; - bytes to = 2; // 20-byte Ethereum address - bytes value = 3; // U256 as big-endian bytes -} - -// Mirror of policies::SpecificMeaning -message SpecificMeaning { - oneof meaning { - EtherTransferMeaning ether_transfer = 1; - TokenTransferMeaning token_transfer = 2; - } -} - -// --- Eval error types --- -message GasLimitExceededViolation { - optional bytes max_gas_fee_per_gas = 1; // U256 as big-endian bytes - optional bytes max_priority_fee_per_gas = 2; // U256 as big-endian bytes -} - -message EvalViolation { - oneof kind { - bytes invalid_target = 1; // 20-byte Ethereum address - GasLimitExceededViolation gas_limit_exceeded = 2; - google.protobuf.Empty rate_limit_exceeded = 3; - google.protobuf.Empty volumetric_limit_exceeded = 4; - google.protobuf.Empty invalid_time = 5; - google.protobuf.Empty invalid_transaction_type = 6; - } -} - -// Transaction was classified but no grant covers it -message NoMatchingGrantError { - SpecificMeaning meaning = 1; -} - -// Transaction was classified and a grant was found, but constraints were violated -message PolicyViolationsError { - SpecificMeaning meaning = 1; - repeated EvalViolation violations = 2; -} - -// top-level error returned when transaction evaluation fails -message TransactionEvalError { - oneof kind { - google.protobuf.Empty contract_creation_not_supported = 1; - google.protobuf.Empty unsupported_transaction_type = 2; - NoMatchingGrantError no_matching_grant = 3; - PolicyViolationsError policy_violations = 4; - } -} - // --- UserAgent grant management --- message EvmGrantCreateRequest { SharedSettings shared = 1; @@ -197,7 +134,7 @@ message EvmSignTransactionRequest { message EvmSignTransactionResponse { oneof result { bytes signature = 1; // 65-byte signature: r[32] || s[32] || v[1] - TransactionEvalError eval_error = 2; + arbiter.shared.evm.TransactionEvalError eval_error = 2; EvmError error = 3; } } @@ -209,8 +146,8 @@ message EvmAnalyzeTransactionRequest { message EvmAnalyzeTransactionResponse { oneof result { - SpecificMeaning meaning = 1; - TransactionEvalError eval_error = 2; + arbiter.shared.evm.SpecificMeaning meaning = 1; + arbiter.shared.evm.TransactionEvalError eval_error = 2; EvmError error = 3; } } diff --git a/protobufs/shared/client.proto b/protobufs/shared/client.proto new file mode 100644 index 0000000..b36c840 --- /dev/null +++ b/protobufs/shared/client.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +package arbiter.shared; + +message ClientInfo { + string name = 1; + optional string description = 2; + optional string version = 3; +} diff --git a/protobufs/shared/evm.proto b/protobufs/shared/evm.proto new file mode 100644 index 0000000..afac94d --- /dev/null +++ b/protobufs/shared/evm.proto @@ -0,0 +1,68 @@ +syntax = "proto3"; + +package arbiter.shared.evm; + +import "google/protobuf/empty.proto"; + +message EtherTransferMeaning { + bytes to = 1; // 20-byte Ethereum address + bytes value = 2; // U256 as big-endian bytes +} + +message TokenInfo { + string symbol = 1; + bytes address = 2; // 20-byte Ethereum address + uint64 chain_id = 3; +} + +// Mirror of token_transfers::Meaning +message TokenTransferMeaning { + TokenInfo token = 1; + bytes to = 2; // 20-byte Ethereum address + bytes value = 3; // U256 as big-endian bytes +} + +// Mirror of policies::SpecificMeaning +message SpecificMeaning { + oneof meaning { + EtherTransferMeaning ether_transfer = 1; + TokenTransferMeaning token_transfer = 2; + } +} + +message GasLimitExceededViolation { + optional bytes max_gas_fee_per_gas = 1; // U256 as big-endian bytes + optional bytes max_priority_fee_per_gas = 2; // U256 as big-endian bytes +} + +message EvalViolation { + oneof kind { + bytes invalid_target = 1; // 20-byte Ethereum address + GasLimitExceededViolation gas_limit_exceeded = 2; + google.protobuf.Empty rate_limit_exceeded = 3; + google.protobuf.Empty volumetric_limit_exceeded = 4; + google.protobuf.Empty invalid_time = 5; + google.protobuf.Empty invalid_transaction_type = 6; + } +} + +// Transaction was classified but no grant covers it +message NoMatchingGrantError { + SpecificMeaning meaning = 1; +} + +// Transaction was classified and a grant was found, but constraints were violated +message PolicyViolationsError { + SpecificMeaning meaning = 1; + repeated EvalViolation violations = 2; +} + +// top-level error returned when transaction evaluation fails +message TransactionEvalError { + oneof kind { + google.protobuf.Empty contract_creation_not_supported = 1; + google.protobuf.Empty unsupported_transaction_type = 2; + NoMatchingGrantError no_matching_grant = 3; + PolicyViolationsError policy_violations = 4; + } +} diff --git a/protobufs/shared/vault.proto b/protobufs/shared/vault.proto new file mode 100644 index 0000000..795539f --- /dev/null +++ b/protobufs/shared/vault.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +package arbiter.shared; + +enum VaultState { + VAULT_STATE_UNSPECIFIED = 0; + VAULT_STATE_UNBOOTSTRAPPED = 1; + VAULT_STATE_SEALED = 2; + VAULT_STATE_UNSEALED = 3; + VAULT_STATE_ERROR = 4; +} diff --git a/protobufs/user_agent/sdk_client.proto b/protobufs/user_agent/sdk_client.proto index 62f2a70..30cfe5b 100644 --- a/protobufs/user_agent/sdk_client.proto +++ b/protobufs/user_agent/sdk_client.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package arbiter.user_agent.sdk_client; -import "client.proto"; +import "shared/client.proto"; import "google/protobuf/empty.proto"; enum Error { @@ -20,7 +20,7 @@ message RevokeRequest { message Entry { int32 id = 1; bytes pubkey = 2; - arbiter.client.ClientInfo info = 3; + arbiter.shared.ClientInfo info = 3; int32 created_at = 4; } @@ -44,7 +44,7 @@ message ListResponse { message ConnectionRequest { bytes pubkey = 1; - arbiter.client.ClientInfo info = 2; + arbiter.shared.ClientInfo info = 2; } message ConnectionResponse { diff --git a/protobufs/user_agent/vault/vault.proto b/protobufs/user_agent/vault/vault.proto index 640b0d3..832f13c 100644 --- a/protobufs/user_agent/vault/vault.proto +++ b/protobufs/user_agent/vault/vault.proto @@ -3,17 +3,10 @@ syntax = "proto3"; package arbiter.user_agent.vault; import "google/protobuf/empty.proto"; +import "shared/vault.proto"; import "user_agent/vault/bootstrap.proto"; import "user_agent/vault/unseal.proto"; -enum VaultState { - VAULT_STATE_UNSPECIFIED = 0; - VAULT_STATE_UNBOOTSTRAPPED = 1; - VAULT_STATE_SEALED = 2; - VAULT_STATE_UNSEALED = 3; - VAULT_STATE_ERROR = 4; -} - message Request { oneof payload { google.protobuf.Empty query_state = 1; @@ -24,7 +17,7 @@ message Request { message Response { oneof payload { - VaultState state = 1; + arbiter.shared.VaultState state = 1; unseal.Response unseal = 2; bootstrap.Response bootstrap = 3; }