syntax = "proto3"; package wire.federator; // These definitions are part of the federation protocol. // // 1. A component (e.g. 'brig') will send some data of type 'FederatedRequest' to // the 'federator' server (more precisely: the 'Outward' service part of the federator) within a same private network. // 2. The federator will use the domain from the 'FederatedRequest' to discover // where to send some data of type 'Request' to. // 3. On the other side, a publicly exposed 'Inward' service (also co-hosted on the // federator) will turn the received 'Request' into a 'Response' by making a call to a // component (e.g. brig) on its private network. enum Component { Brig = 0; Galley = 1; } message InwardResponse { oneof response { InwardError err = 1; bytes body = 2; } } message OutwardResponse { oneof response { OutwardError outErr = 1; InwardError inErr = 2; bytes body = 3; } } message OutwardError { enum ErrorType { RemoteNotFound = 0; DiscoveryFailed = 1; ConnectionRefused = 2; TLSFailure = 3; VersionMismatch = 4; FederationDeniedByRemote = 5; FederationDeniedLocally = 6; TooMuchConcurrency = 7; GrpcError = 8; InvalidRequest = 9; } ErrorType type = 1; string msg = 2; } message InwardError { enum ErrorType { IOther = 0; IAuthenticationFailed = 1; IFederationDeniedByRemote = 2; IInvalidEndpoint = 3; IForbiddenEndpoint = 4; IDiscoveryFailed = 5; } ErrorType type = 1; string msg = 2; } // The envelope message which is sent from brig to the Outward service of a local federator message FederatedRequest { string domain = 1; Request request = 2; } // The request message is not a high-level protocol of federation. Instead, it // allows encoding more-or-less arbitrary HTTP requests. The idea is to separate // the concern of discovery and routing (federator's domain) from the concern of // actual API routes available in a federated context (those are currently // specified within each component. This may change in the future, however). // FUTUREWORK(Akshay): detail the design thoughts behind this type a bit more message Request { Component component = 1; bytes path = 2; //Maybe this can be made into a 'function name' bytes body = 3; string originDomain = 4; } // The federator actually listens on two ports and exposes two services: // // 'Outward' is only accessible from within the private network and serves // as a forwarding service to other backends. // // Example: 'brig' will use Outward.call on an internal server on // 127.0.0.1:8097 to (indirectly) talk to the federated world. service Outward { rpc call (FederatedRequest) returns (OutwardResponse); } // 'Inward' is exposed to the public internet (via nginx) and serves as a // forwarding service within its own private network // // Example: 'federator' will use Inward.call on federator.another-domain to // talk to a component inside the group of servers of another-domain // which is not directly accessible. service Inward { rpc call (Request) returns (InwardResponse); }