syntax = "proto3"; // Proto field names should be snake_case, but some plugins don't convert to // camel like they should, so we use camelCase here. package service; option go_package=".;service"; import "patch/go.proto"; service RPC { rpc KeyGenerate(KeyGenerateRequest) returns (KeyGenerateResponse) {} rpc Keys(KeysRequest) returns (KeysResponse) {} rpc Key(KeyRequest) returns (KeyResponse) {} rpc KeyImport(KeyImportRequest) returns (KeyImportResponse) {} rpc KeyExport(KeyExportRequest) returns (KeyExportResponse) {} rpc KeyRemove(KeyRemoveRequest) returns (KeyRemoveResponse) {} rpc Sign(SignRequest) returns (SignResponse) {} rpc SignFile(stream SignFileInput) returns (stream SignFileOutput) {} rpc SignStream(stream SignInput) returns (stream SignOutput) {} rpc Verify(VerifyRequest) returns (VerifyResponse) {} rpc VerifyFile(stream VerifyFileInput) returns (stream VerifyFileOutput) {} rpc VerifyStream(stream VerifyInput) returns (stream VerifyOutput) {} rpc VerifyDetached(VerifyDetachedRequest) returns (VerifyDetachedResponse) {} rpc VerifyDetachedFile(stream VerifyDetachedFileInput) returns (VerifyDetachedResponse) {} rpc VerifyDetachedStream(stream VerifyDetachedInput) returns (VerifyDetachedResponse) {} rpc Encrypt(EncryptRequest) returns (EncryptResponse) {} rpc EncryptStream(stream EncryptInput) returns (stream EncryptOutput) {} rpc EncryptFile(stream EncryptFileInput) returns (stream EncryptFileOutput) {} rpc Decrypt(DecryptRequest) returns (DecryptResponse) {} rpc DecryptStream(stream DecryptInput) returns (stream DecryptOutput) {} rpc DecryptFile(stream DecryptFileInput) returns (stream DecryptFileOutput) {} rpc Sigchain(SigchainRequest) returns (SigchainResponse) {} rpc Statement(StatementRequest) returns (StatementResponse) {} rpc StatementCreate(StatementCreateRequest) returns (StatementCreateResponse) {} rpc StatementRevoke(StatementRevokeRequest) returns (StatementRevokeResponse) {} rpc User(UserRequest) returns (UserResponse) {} rpc UserSearch(UserSearchRequest) returns (UserSearchResponse) {} rpc UserService(UserServiceRequest) returns (UserServiceResponse) {} rpc UserSign(UserSignRequest) returns (UserSignResponse) {} rpc UserAdd(UserAddRequest) returns (UserAddResponse) {} rpc Search(SearchRequest) returns (SearchResponse) {} rpc Secret(SecretRequest) returns (SecretResponse) {} rpc SecretSave(SecretSaveRequest) returns (SecretSaveResponse) {} rpc SecretRemove(SecretRemoveRequest) returns (SecretRemoveResponse) {} rpc Secrets(SecretsRequest) returns (SecretsResponse) {} rpc Pull(PullRequest) returns (PullResponse) {} rpc Push(PushRequest) returns (PushResponse) {} rpc Wormhole(stream WormholeInput) returns (stream WormholeOutput) {} // These requests do not need auth. // BEGIN NO AUTH rpc AuthSetup(AuthSetupRequest) returns (AuthSetupResponse) {} rpc AuthVault(AuthVaultRequest) returns (AuthVaultResponse) {} rpc AuthUnlock(AuthUnlockRequest) returns (AuthUnlockResponse) {} rpc AuthLock(AuthLockRequest) returns (AuthLockResponse) {} rpc AuthReset(AuthResetRequest) returns (AuthResetResponse) {} rpc AuthRecover(AuthRecoverRequest) returns (AuthRecoverResponse) {} rpc RuntimeStatus(RuntimeStatusRequest) returns (RuntimeStatusResponse) {} rpc Rand(RandRequest) returns (RandResponse) {} rpc RandPassword(RandPasswordRequest) returns (RandPasswordResponse) {} // END NO AUTH // Auth (edit) rpc AuthProvision(AuthProvisionRequest) returns (AuthProvisionResponse) {} rpc AuthDeprovision(AuthDeprovisionRequest) returns (AuthDeprovisionResponse) {} rpc AuthProvisions(AuthProvisionsRequest) returns (AuthProvisionsResponse) {} rpc AuthPasswordChange(AuthPasswordChangeRequest) returns (AuthPasswordChangeResponse) {} // Vault rpc VaultAuth(VaultAuthRequest) returns (VaultAuthResponse) {} rpc VaultSync(VaultSyncRequest) returns (VaultSyncResponse) {} rpc VaultUnsync(VaultUnsyncRequest) returns (VaultUnsyncResponse) {} rpc VaultStatus(VaultStatusRequest) returns (VaultStatusResponse) {} rpc VaultUpdate(VaultUpdateRequest) returns (VaultUpdateResponse) {} // DB rpc Collections(CollectionsRequest) returns (CollectionsResponse) {} rpc Documents(DocumentsRequest) returns (DocumentsResponse) {} rpc DocumentDelete(DocumentDeleteRequest) returns (DocumentDeleteResponse) {} // Config rpc ConfigGet(ConfigGetRequest) returns (ConfigGetResponse) {} rpc ConfigSet(ConfigSetRequest) returns (ConfigSetResponse) {} // Admin rpc AdminSignURL(AdminSignURLRequest) returns (AdminSignURLResponse) {} rpc AdminCheck(AdminCheckRequest) returns (AdminCheckResponse) {} // // Experimental // // Channels rpc Channels(ChannelsRequest) returns (ChannelsResponse) {} rpc ChannelCreate(ChannelCreateRequest) returns (ChannelCreateResponse) {} rpc ChannelInvite(ChannelInviteRequest) returns (ChannelInviteResponse) {} rpc ChannelLeave(ChannelLeaveRequest) returns (ChannelLeaveResponse) {} rpc ChannelRead(ChannelReadRequest) returns (ChannelReadResponse) {} // Follow rpc Follow(FollowRequest) returns (FollowResponse) {} rpc Follows(FollowsRequest) returns (FollowsResponse) {} // Messages rpc MessagePrepare(MessagePrepareRequest) returns (MessagePrepareResponse) {} rpc MessageCreate(MessageCreateRequest) returns (MessageCreateResponse) {} rpc Messages(MessagesRequest) returns (MessagesResponse) {} // Relay rpc Relay(RelayRequest) returns (stream RelayOutput) {} } message SignRequest { bytes data = 1; string signer = 5; // Armored, if true, output will be armored. bool armored = 10; // Detached, if true, output will be just the signature. bool detached = 11; } message SignResponse { // Data is signed output. bytes data = 1; string kid = 2 [(go.field) = {name: "KID"}]; } message SignFileInput { // In is input file path. string in = 1; // Out file path (or sig if detached). string out = 2; string signer = 5; // Armored, if true, output will be armored. bool armored = 10; // Detached, if true, output will be just the signature. bool detached = 11; } message SignFileOutput { string kid = 1 [(go.field) = {name: "KID"}]; string out = 2; int32 bytes = 10; int32 total = 11; } message VerifyRequest { // Data is verified output. bytes data = 1; } message VerifyResponse { // Data (if out is not specified in request). bytes data = 1; Key signer = 2; } message VerifyDetachedRequest { // Data to verify. bytes data = 1; bytes sig = 2; } message VerifyDetachedResponse { Key signer = 1; } message VerifyInput { // Data to verify. bytes data = 1; } message VerifyOutput { // Data, verified. If empty, is EOF. bytes data = 1; Key signer = 2; } message VerifyFileInput { // In is input file path. string in = 1; // Out is the output file name or directory to save to. string out = 2; } message VerifyFileOutput { Key signer = 1; string out = 2; } message VerifyDetachedFileInput { // In is input file path. string in = 1; // Signature (detached). bytes sig = 2; } message VerifyDetachedInput { // Data to verify. bytes data = 1; // Signature (detached). bytes sig = 2; } message Statement { // Sig is the signature bytes. bytes sig = 1; // Data that was signed. bytes data = 2; // KID is the key that signed. string kid = 3 [(go.field) = {name: "KID"}]; // Seq in a sigchain (1 is root). int32 seq = 4; // Prev is a hash of the previous item in the sigchain. bytes prev = 5; // Revoke refers to a previous signed seq to revoke. int32 revoke = 6; // Timestamp ... int64 timestamp = 7; // Type (optional). string type = 8; } message SigchainRequest { string kid = 1 [(go.field) = {name: "KID"}]; } message SigchainResponse { Key key = 1; repeated Statement statements = 2; } message StatementRequest { string kid = 1 [(go.field) = {name: "KID"}]; int32 seq = 2; } message StatementResponse { Statement statement = 1; } message StatementCreateRequest { bytes data = 1; string kid = 2 [(go.field) = {name: "KID"}]; // Local, if true, won't save to the current key server. bool local = 5; } message StatementCreateResponse { Statement statement = 1; } message StatementRevokeRequest { // Seq to revoke. int32 seq = 1; string kid = 2 [(go.field) = {name: "KID"}]; // Local, if true, won't save to the current key server. bool local = 5; } message StatementRevokeResponse { Statement statement = 1; } message SignInput { bytes data = 1; // In is input file path (if data is not specified). string in = 2; // Out is output file path (required if in specified). string out = 3; string signer = 5; // Armored, if true, output will be armored. bool armored = 10; // Detached, if true, output will be just the signature. bool detached = 11; } message SignOutput { // Data, signed. bytes data = 1; string kid = 2 [(go.field) = {name: "KID"}]; } enum EncryptMode { option (go.enum) = {name: "EncryptMode"}; DEFAULT_ENCRYPT = 0 [(go.value) = {name: "DefaultEncrypt"}]; SALTPACK_ENCRYPT = 1 [(go.value) = {name: "SaltpackEncrypt"}]; SALTPACK_SIGNCRYPT = 3 [(go.value) = {name: "SaltpackSigncrypt"}]; } message EncryptOptions { // Armored, if true will return armored string output. bool armored = 1; // Mode is the encryption mode. EncryptMode mode = 2; // NoSenderRecipient if true, won't add sender to recipients list. bool noSenderRecipient = 3; // NoSign if true, won't sign with sender. bool noSign = 4; } message EncryptRequest { // Data to encrypt. bytes data = 1; // Recipients to encrypt to. repeated string recipients = 3; // Sender, or anonymous. string sender = 4; // Options for encrypt. EncryptOptions options = 10; } message EncryptResponse { bytes data = 1; string info = 2; } message EncryptFileInput { // In is input file path. string in = 1; // Out is output file path. string out = 2; // Recipients to encrypt to. repeated string recipients = 3; // Sender, or anonymous. string sender = 4; // Options for encrypt. EncryptOptions options = 10; } message EncryptFileOutput { // Out is the output decrypted file path. string out = 2; int32 bytes = 10; int32 total = 11; } message EncryptInput { // Data to encrypt. Send empty byte slice as last message. bytes data = 1; // Recipients to encrypt to. repeated string recipients = 3; // Sender, or anonymous. string sender = 4; // Options for encrypt. EncryptOptions options = 10; } message EncryptOutput { // Data, encrypted. bytes data = 1; } message DecryptRequest { // Data to decrypt. bytes data = 1; } message DecryptResponse { // Data decrypted. bytes data = 1; // Sender (if not anonymous) Key sender = 2; // Mode is the encryption mode for the data. EncryptMode mode = 5; } message DecryptFileInput { // In is the input encrypted file path. string in = 1; // Out is the output file name or directory to save to. string out = 2; } message DecryptFileOutput { Key sender = 1; // Out is the output file path. string out = 2; int32 bytes = 10; int32 total = 11; // Mode is the encryption mode we detected. EncryptMode mode = 5; } message DecryptInput { // Data, encrypted. bytes data = 1; } message DecryptOutput { // Data, decrypted. If empty, is EOF. bytes data = 1; // Sender (if not anonymous) Key sender = 2; // Mode is the encryption mode for the data. EncryptMode mode = 5; } message RuntimeStatusRequest {} message RuntimeStatusResponse { // Version of running service. string version = 1; // AppName app name. string appName = 2; // Exe is the service executable path. string exe = 4; // AuthStatus is the status of auth. AuthStatus authStatus = 5; // SyncStatus is the status of vault sync. bool sync = 6; // FIDO2 available. bool fido2 = 20 [(go.field) = {name: "FIDO2"}]; } enum AuthStatus { option (go.enum) = {name: "AuthStatus"}; AUTH_UNKNOWN = 0 [(go.value) = {name: "AuthUnknown"}]; // AuthSetupNeeded if setup needed. AUTH_SETUP_NEEDED = 1 [(go.value) = {name: "AuthSetupNeeded"}]; // AuthUnlocked if unlocked. AUTH_UNLOCKED = 2 [(go.value) = {name: "AuthUnlocked"}]; // AuthLocked if locked. AUTH_LOCKED = 3 [(go.value) = {name: "AuthLocked"}]; } enum AuthType { option (go.enum) = {name: "AuthType"}; UNKNOWN_AUTH = 0 [(go.value) = {name: "UnknownAuth"}]; // PasswordAuth uses password with salt (argon2id). PASSWORD_AUTH = 10 [(go.value) = {name: "PasswordAuth"}]; // PaperKeyAuth uses a BIP39 phrase representing a key. PAPER_KEY_AUTH = 11 [(go.value) = {name: "PaperKeyAuth"}]; // FIDO2HMACSecretAuth uses a FIDO2 HMAC-Secret extension. FIDO2_HMAC_SECRET_AUTH = 20 [(go.value) = {name: "FIDO2HMACSecretAuth"}]; } message AuthSetupRequest { // Secret for auth depending on auth type, e.g. password, FIDO2 pin, etc. string secret = 1; // Type for auth. AuthType type = 2; // Device path (for FIDO2). string device = 5; } message AuthSetupResponse {} message AuthVaultRequest { string phrase = 1; } message AuthVaultResponse {} message AuthUnlockRequest { // Secret for auth depending on auth type, e.g. password, pin, etc. string secret = 1; // Type for auth. AuthType type = 2; // Client name. string client = 6; } message AuthUnlockResponse { // AuthToken to use for requests. string authToken = 1; } message AuthProvisionRequest { // Secret for auth depending on auth type, e.g. password, phrase, FIDO2 pin, etc. string secret = 1; // Type for auth. AuthType type = 2; // Device path (for FIDO2). string device = 5; // Generate (for FIDO2 make credential). bool generate = 7; } message AuthProvisionResponse { AuthProvision provision = 1; } message AuthDeprovisionRequest { string id = 1 [(go.field) = {name: "ID"}]; } message AuthDeprovisionResponse {} message AuthPasswordChangeRequest { string old = 1; string new = 2; } message AuthPasswordChangeResponse {} message AuthProvision { string id = 1 [(go.field) = {name: "ID"}]; AuthType type = 2; int64 createdAt = 3; // For FIDO2 // AAGUID is a device "identifier" (only unique across batches for privacy reasons). string aaguid = 100 [(go.field) = {name: "AAGUID"}]; bool noPin = 101; } message AuthProvisionsRequest {} message AuthProvisionsResponse { repeated AuthProvision provisions = 1; } message AuthLockRequest {} message AuthLockResponse {} message AuthResetRequest { string appName = 1; } message AuthResetResponse {} message AuthRecoverRequest { string paperKey = 1; string newPassword = 2; } message AuthRecoverResponse { string authToken = 1; } message KeyGenerateRequest { string type = 1; } message KeyGenerateResponse { string kid = 1 [(go.field) = {name: "KID"}]; } message UserServiceRequest { // KID to use, or if empty the current key. string kid = 1 [(go.field) = {name: "KID"}]; // Service such as twitter, github. string service = 2; } message UserServiceResponse { // Service such as twitter, github. string service = 1; } message UserSignRequest { // KID to use, or if empty the current key. string kid = 1 [(go.field) = {name: "KID"}]; // Service such as twitter, github. string service = 2; // Name is username on the service. string name = 3; } message UserSignResponse { // Message is signed message. string message = 1; // Name in request. string name = 2; } message UserAddRequest { // KID to use, or if empty the current key. string kid = 1 [(go.field) = {name: "KID"}]; // Service such as twitter, github. string service = 2; // Name is username on the service. string name = 3; // URL is location of signed message on the service. string url = 4 [(go.field) = {name: "URL"}]; // Local, if true, won't save to the current key server. bool local = 5; } message UserAddResponse { User user = 1; Statement statement = 2; } enum ExportType { option (go.enum) = {name: "ExportType"}; DEFAULT_EXPORT_TYPE = 0 [(go.value) = {name: "DefaultExport"}]; SSH_EXPORT_TYPE = 1 [(go.value) = {name: "SSHExport"}]; } message KeyExportRequest { string kid = 1 [(go.field) = {name: "KID"}]; string password = 2; ExportType type = 3; bool public = 4; bool noPassword = 5; } message KeyExportResponse { bytes export = 1; } message KeyImportRequest { bytes in = 1; string password = 2; bool update = 3; } message KeyImportResponse { string kid = 1 [(go.field) = {name: "KID"}]; } message KeyRemoveRequest { // KID of key to remove. string kid = 1 [(go.field) = {name: "KID"}]; } message KeyRemoveResponse {} message Key { // ID identifier. string id = 1 [(go.field) = {name: "ID"}]; // Type of key. string type = 3; // IsPrivate if private key. bool isPrivate = 4; // User associated with this key. User user = 6; // Saved if saved locally. bool saved = 10; // SigchainLength is length of sigchain (if any). int32 sigchainLength = 40; int64 sigchainUpdatedAt = 41; } message KeyRequest { // Key can be kid or user@service. string key = 1; // Search, if true, will search for the key on the server. bool search = 4; // Update, if true, will update the sigchain from the server. bool update = 5; } message KeyResponse { Key key = 1; } enum SortDirection { option (go.enum) = {name: "SortDirection"}; ASC = 0 [(go.value) = {name: "SortAsc"}]; DESC = 1 [(go.value) = {name: "SortDesc"}]; } message KeysRequest { string query = 1; repeated string types = 2; string sortField = 10; SortDirection sortDirection = 11; } message KeysResponse { repeated Key keys = 1; string sortField = 10; SortDirection sortDirection = 11; } enum SecretType { option (go.enum) = {name: "SecretType"}; UNKNOWN_SECRET_TYPE = 0 [(go.value) = {name: "UnknownSecret"}]; PASSWORD_SECRET = 10 [(go.value) = {name: "PasswordSecret"}]; CONTACT_SECRET = 11 [(go.value) = {name: "ContactSecret"}]; CARD_SECRET = 12 [(go.value) = {name: "CardSecret"}]; NOTE_SECRET = 13 [(go.value) = {name: "NoteSecret"}]; } message Secret { string id = 1 [(go.field) = {name: "ID"}]; string name = 2; SecretType type = 3; string username = 10; string password = 11; string url = 20 [(go.field) = {name: "URL"}]; string notes = 30; int64 createdAt = 100; int64 updatedAt = 101; } message SecretRequest { string id = 1 [(go.field) = {name: "ID"}]; } message SecretResponse { Secret secret = 1; } message SecretSaveRequest { Secret secret = 1; } message SecretSaveResponse { Secret secret = 1; } message SecretRemoveRequest { string id = 1 [(go.field) = {name: "ID"}]; } message SecretRemoveResponse {} message SecretsRequest { string query = 1; string sortField = 10; SortDirection sortDirection = 11; } message SecretsResponse { repeated Secret secrets = 1; string sortField = 10; SortDirection sortDirection = 11; } enum Encoding { option (go.enum) = {name: "Encoding"}; HEX = 0 [(go.value) = {name: "Hex"}]; BASE62 = 1 [(go.value) = {name: "Base62"}]; BASE58 = 2 [(go.value) = {name: "Base58"}]; BASE32 = 3 [(go.value) = {name: "Base32"}]; BASE16 = 4 [(go.value) = {name: "Base16"}]; BASE64 = 5 [(go.value) = {name: "Base64"}]; SALTPACK = 6 [(go.value) = {name: "Saltpack"}]; BIP39 = 7 [(go.value) = {name: "BIP39"}]; } message RandRequest { int32 numBytes = 1; Encoding encoding = 2; bool noPadding = 10; bool lowercase = 11; } message RandResponse { string data = 1; } message RandPasswordRequest { int32 length = 1; } message RandPasswordResponse { string password = 1; } message PullRequest { string key = 1; } message PullResponse { repeated string kids = 1 [(go.field) = {name: "KIDs"}]; } message PushRequest { string key = 1; bool remoteCheck = 2; } message PushResponse { string kid = 1 [(go.field) = {name: "KID"}]; repeated string urls = 2 [(go.field) = {name: "URLs"}]; } message Collection { string path = 1; } message CollectionsRequest { string parent = 1; // DB is "service" or "vault". string db = 5 [(go.field) = {name: "DB"}]; } message CollectionsResponse { repeated Collection collections = 1; } message Document { string path = 1; string value = 2; int64 createdAt = 10; int64 updatedAt = 11; } message DocumentsRequest { string prefix = 1; // DB is "service" or "vault". string db = 5 [(go.field) = {name: "DB"}]; } message DocumentsResponse { repeated Document documents = 1; } message DocumentDeleteRequest { string path = 1; string db = 5 [(go.field) = {name: "DB"}]; } message DocumentDeleteResponse {} enum UserStatus { option (go.enum) = {name: "UserStatus"}; USER_UNKNOWN = 0 [(go.value) = {name: "UserStatusUnknown"}]; USER_OK = 1 [(go.value) = {name: "UserStatusOK"}]; USER_RESOURCE_NOT_FOUND = 20 [(go.value) = {name: "UserStatusResourceNotFound"}]; USER_CONTENT_NOT_FOUND = 30 [(go.value) = {name: "UserStatusContentNotFound"}]; USER_CONTENT_INVALID = 31 [(go.value) = {name: "UserStatusContentInvalid"}]; USER_CONN_FAILURE = 40 [(go.value) = {name: "UserStatusConnFailure"}]; USER_FAILURE = 50 [(go.value) = {name: "UserStatusFailure"}]; } message User { string id = 1 [(go.field) = {name: "ID"}]; string name = 2; string kid = 3 [(go.field) = {name: "KID"}]; int32 seq = 4; string service = 5; string url = 6 [(go.field) = {name: "URL"}]; UserStatus status = 10; int64 verifiedAt = 11; int64 timestamp = 12; bool proxied = 13; string err = 20; } message UserRequest { string kid = 1 [(go.field) = {name: "KID"}]; bool local = 4; } message UserResponse { User user = 1; } message UserSearchRequest { string query = 1; int32 limit = 3; bool local = 4; } message UserSearchResponse { repeated User users = 1; } message SearchRequest { string query = 1; } message SearchResponse { repeated Key keys = 1; } message VaultSyncRequest {} message VaultSyncResponse {} message VaultUnsyncRequest {} message VaultUnsyncResponse {} message VaultAuthRequest {} message VaultAuthResponse { string phrase = 1; } message VaultStatusRequest {} message VaultStatusResponse { string kid = 1 [(go.field) = {name: "KID"}]; int64 syncedAt = 2; } message VaultUpdateRequest {} message VaultUpdateResponse {} enum MessageStatus { option (go.enum) = {name: "MessageStatus"}; MESSAGE_SENT = 0 [(go.value) = {name: "MessageSent"}]; MESSAGE_PENDING = 1 [(go.value) = {name: "MessagePending"}]; MESSAGE_ERROR = 2 [(go.value) = {name: "MessageError"}]; } message Message { string id = 1 [(go.field) = {name: "ID"}]; Key sender = 2; repeated string text = 10; MessageStatus status = 20; int64 createdAt = 31; } message MessagePrepareRequest { string sender = 1; string channel = 2; string text = 11; } message MessagePrepareResponse { Message message = 1; } message MessageCreateRequest { string sender = 1; string channel = 2; // ID is optional, if message was prepared you can use that ID, otherwise it // is autogenerated. string id = 10 [(go.field) = {name: "ID"}]; string text = 11; } message MessageCreateResponse { Message message = 1; } message MessagesRequest { string channel = 1; // Update, if true will update from the server. bool update = 5; } message MessagesResponse { repeated Message messages = 1; } message RelayRequest { repeated string keys = 1; string user = 2; } message RelayOutput { string channel = 1; string user = 2; int64 index = 3; } message Channel { string id = 1 [(go.field) = {name: "ID"}]; string name = 2; string snippet = 3; int64 updatedAt = 4; int64 index = 5; int64 readIndex = 10; } message ChannelsRequest { string user = 1; } message ChannelsResponse { repeated Channel channels = 1; } message ChannelCreateRequest { string name = 1; string user = 2; } message ChannelCreateResponse { Channel channel = 1; } message ChannelLeaveRequest { string channel = 1; } message ChannelLeaveResponse {} message ChannelReadRequest { string channel = 1; int64 index = 2; } message ChannelReadResponse {} message ChannelInviteRequest { string channel = 1; repeated string recipients = 2; string sender = 3; } message ChannelInviteResponse { Message message = 1; } message Follow { string recipient = 1; string sender = 2; } message FollowRequest { string recipient = 1; string sender = 2; } message FollowResponse { Follow follow = 1; } message FollowsRequest { string recipient = 1; bool update = 2; } message FollowsResponse { repeated Follow follows = 1; } message AdminSignURLRequest { string signer = 1; string method = 2; string url = 3 [(go.field) = {name: "URL"}]; } message AdminSignURLResponse { string auth = 1; string url = 2 [(go.field) = {name: "URL"}]; string curl = 3 [(go.field) = {name: "CURL"}]; } message AdminCheckRequest { string signer = 1; string check = 2; } message AdminCheckResponse {} message Config { message App { string location = 1; repeated string history = 2; bool navMinimized = 100; } message Encrypt { repeated string recipients = 1; string sender = 2; bool noSenderRecipient = 3; bool noSign = 4; } message Sign { string signer = 1; } App app = 1; Encrypt encrypt = 10; Sign sign = 11; } message ConfigGetRequest { string name = 1; } message ConfigGetResponse { Config config = 1; } message ConfigSetRequest { string name = 1; Config config = 2; } message ConfigSetResponse {} message WormholeInput { string sender = 1; string recipient = 2; string invite = 3; string id = 10 [(go.field) = {name: "ID"}]; string text = 11; } enum WormholeStatus { option (go.enum) = {name: "WormholeStatus"}; WORMHOLE_DEFAULT = 0 [(go.value) = {name: "WormholeDefault"}]; // WormholeStarting if starting. WORMHOLE_STARTING = 10 [(go.value) = {name: "WormholeStarting"}]; // WormholeOffering if offering. WORMHOLE_OFFERING = 20 [(go.value) = {name: "WormholeOffering"}]; // WormholeAnswering if answering. WORMHOLE_ANSWERING = 21 [(go.value) = {name: "WormholeAnswering"}]; // WormholeHandshake if found offer/answer and trying to SCTP/Noise handshake. WORMHOLE_HANDSHAKE = 40 [(go.value) = {name: "WormholeHandshake"}]; // WormholeConnected if connected WORMHOLE_CONNECTED = 100 [(go.value) = {name: "WormholeConnected"}]; // WormholeClosed if closed WORMHOLE_CLOSED = 200 [(go.value) = {name: "WormholeClosed"}]; } message WormholeMessage { string id = 1 [(go.field) = {name: "ID"}]; Key sender = 2; Key recipient = 3; WormholeMessageStatus status = 5; string text = 10; int64 createdAt = 21; } message WormholeOutput { WormholeMessage message = 1; WormholeStatus status = 2; } enum WormholeMessageStatus { option (go.enum) = {name: "WormholeMessageStatus"}; WORMHOLE_MESSAGE_SENT = 0 [(go.value) = {name: "WormholeMessageSent"}]; WORMHOLE_MESSAGE_PENDING = 1 [(go.value) = {name: "WormholeMessagePending"}]; WORMHOLE_MESSAGE_ACK = 2 [(go.value) = {name: "WormholeMessageAck"}]; }