1// SPDX-License-Identifier: MIT
2
3syntax = "proto3";
4
5package ermite;
6
7import "google/protobuf/timestamp.proto";
8
9// SettingsScope says where a secret or a variable lives, like the scopes of
10// GitHub Actions. A job sees the ones of its instance, its repository and its
11// environment, and the narrowest scope wins: environment over repository over
12// instance.
13message SettingsScope {
14 // Where is the scope. It is required: a request without it is
15 // invalid_argument.
16 oneof where {
17 // Instance is the whole server. It must be true when set. It needs a token
18 // that is not restricted to repositories, or the root token.
19 bool instance = 1;
20 // Repo is the name of a repository.
21 string repo = 2;
22 // Environment is an environment of a repository.
23 EnvironmentRef environment = 3;
24 }
25}
26
27// EnvironmentRef names an environment of a repository.
28message EnvironmentRef {
29 // Repo is the repository name.
30 string repo = 1;
31 // Name is the environment name, see Environment.name.
32 string name = 2;
33}
34
35// Secret describes a stored secret. It never contains the value: a value can
36// be set but not read back.
37message Secret {
38 // Name is the name of the secret, in upper case as the server stores it.
39 string name = 1;
40 // UpdatedAt is when the value was last set.
41 google.protobuf.Timestamp updated_at = 2;
42}
43
44// Variable is a configuration variable. Unlike a secret its value can be read
45// back and it may appear in logs.
46message Variable {
47 // Name is the name of the variable, in upper case as the server stores it.
48 string name = 1;
49 // Value is the value, at most 48 KiB.
50 string value = 2;
51 // UpdatedAt is when the value was last set.
52 google.protobuf.Timestamp updated_at = 3;
53}
54
55// Environment is a named deployment target of a repository, to which secrets
56// and variables can be attached. A workflow job that names an environment
57// creates it on first use, as on GitHub.
58message Environment {
59 // Repo is the repository name.
60 string repo = 1;
61 // Name is the name of the environment, 1 to 255 characters without control
62 // characters, unique in the repository without regard to case. The server
63 // keeps the case it was given.
64 string name = 2;
65 // CreatedAt is when the environment was created.
66 google.protobuf.Timestamp created_at = 3;
67}
68
69// SecretService manages the encrypted secrets that CI jobs receive, like `gh
70// secret` does on GitHub. Names are 1 to 255 characters among letters, digits
71// and "_", do not begin with a digit or with "GITHUB_", and are
72// case-insensitive: the server stores them in upper case.
73//
74// Every RPC needs the secrets:write scope on a token that may access the
75// repository of the scope (a repository-restricted token cannot use the
76// instance scope), or the root token. Tokens limited to branches are refused
77// with permission_denied, whatever their scopes: they never hold the owner's
78// rights. A repository that does not exist or that the caller cannot access
79// gives not_found.
80//
81// Values are encrypted at rest with the server's key. A server without a key
82// refuses to set a secret with failed_precondition and sends no secrets to
83// jobs. The API never returns a value, and the server never logs one.
84//
85// Page sizes and page tokens work as in the other services.
86//
87// Servers that implement it list "ci.secrets" in GetVersionResponse.features.
88service SecretService {
89 // SetSecret creates the secret or replaces its value. Fails with
90 // invalid_argument if the name is not valid, if the value is empty or longer
91 // than 48 KiB (49,152 bytes), or if scope is not set, with not_found if the
92 // environment of the scope does not exist, and with failed_precondition if
93 // the server has no encryption key.
94 rpc SetSecret(SetSecretRequest) returns (SetSecretResponse);
95 // ListSecrets lists the secrets of one scope, ordered by name. It lists only
96 // the secrets set in that scope, not the ones the scope inherits. It never
97 // returns values.
98 rpc ListSecrets(ListSecretsRequest) returns (ListSecretsResponse);
99 // DeleteSecret deletes a secret. Fails with not_found if it does not exist.
100 rpc DeleteSecret(DeleteSecretRequest) returns (DeleteSecretResponse);
101}
102
103// SetSecretRequest names a secret and gives its value.
104message SetSecretRequest {
105 // Scope is where the secret lives.
106 SettingsScope scope = 1;
107 // Name is the name of the secret.
108 string name = 2;
109 // Value is the value in plain text, 1 byte to 48 KiB. It may contain
110 // several lines.
111 string value = 3;
112}
113
114// SetSecretResponse describes the stored secret.
115message SetSecretResponse {
116 // Secret is the secret, without its value.
117 Secret secret = 1;
118}
119
120// ListSecretsRequest selects a page of the secrets of a scope.
121message ListSecretsRequest {
122 // Scope is the scope to list.
123 SettingsScope scope = 1;
124 // PageSize is the maximum number of secrets to return. 0 means the server
125 // default; values above the server maximum are lowered to it.
126 int32 page_size = 2;
127 // PageToken is the next_page_token of a previous response. Empty for the
128 // first page.
129 string page_token = 3;
130}
131
132// ListSecretsResponse is one page of secrets.
133message ListSecretsResponse {
134 // Secrets are the secrets of this page, ordered by name, without values.
135 repeated Secret secrets = 1;
136 // NextPageToken is passed as page_token to get the next page. Empty when
137 // there is no next page.
138 string next_page_token = 2;
139}
140
141// DeleteSecretRequest names the secret to delete.
142message DeleteSecretRequest {
143 // Scope is where the secret lives.
144 SettingsScope scope = 1;
145 // Name is the name of the secret, without regard to case.
146 string name = 2;
147}
148
149// DeleteSecretResponse is empty.
150message DeleteSecretResponse {}
151
152// VariableService manages the configuration variables that CI jobs receive in
153// the "vars" context, like `gh variable` does on GitHub. Names follow the
154// rules of SecretService. Access rules, errors and page handling are those of
155// SecretService, and the same servers (feature "ci.secrets") implement it.
156service VariableService {
157 // SetVariable creates the variable or replaces its value. Fails with
158 // invalid_argument if the name is not valid, if the value is longer than 48
159 // KiB (49,152 bytes) or if scope is not set, and with not_found if the
160 // environment of the scope does not exist. An empty value is allowed.
161 rpc SetVariable(SetVariableRequest) returns (SetVariableResponse);
162 // GetVariable returns one variable of one scope, with its value. Fails with
163 // not_found if it does not exist in that scope.
164 rpc GetVariable(GetVariableRequest) returns (GetVariableResponse);
165 // ListVariables lists the variables of one scope, ordered by name, with
166 // their values. It lists only the variables set in that scope.
167 rpc ListVariables(ListVariablesRequest) returns (ListVariablesResponse);
168 // DeleteVariable deletes a variable. Fails with not_found if it does not
169 // exist.
170 rpc DeleteVariable(DeleteVariableRequest) returns (DeleteVariableResponse);
171}
172
173// SetVariableRequest names a variable and gives its value.
174message SetVariableRequest {
175 // Scope is where the variable lives.
176 SettingsScope scope = 1;
177 // Name is the name of the variable.
178 string name = 2;
179 // Value is the value, at most 48 KiB.
180 string value = 3;
181}
182
183// SetVariableResponse holds the stored variable.
184message SetVariableResponse {
185 // Variable is the variable as stored.
186 Variable variable = 1;
187}
188
189// GetVariableRequest names a variable.
190message GetVariableRequest {
191 // Scope is where the variable lives.
192 SettingsScope scope = 1;
193 // Name is the name of the variable, without regard to case.
194 string name = 2;
195}
196
197// GetVariableResponse holds a variable.
198message GetVariableResponse {
199 // Variable is the variable.
200 Variable variable = 1;
201}
202
203// ListVariablesRequest selects a page of the variables of a scope.
204message ListVariablesRequest {
205 // Scope is the scope to list.
206 SettingsScope scope = 1;
207 // PageSize is the maximum number of variables to return. 0 means the server
208 // default; values above the server maximum are lowered to it.
209 int32 page_size = 2;
210 // PageToken is the next_page_token of a previous response. Empty for the
211 // first page.
212 string page_token = 3;
213}
214
215// ListVariablesResponse is one page of variables.
216message ListVariablesResponse {
217 // Variables are the variables of this page, ordered by name.
218 repeated Variable variables = 1;
219 // NextPageToken is passed as page_token to get the next page. Empty when
220 // there is no next page.
221 string next_page_token = 2;
222}
223
224// DeleteVariableRequest names the variable to delete.
225message DeleteVariableRequest {
226 // Scope is where the variable lives.
227 SettingsScope scope = 1;
228 // Name is the name of the variable, without regard to case.
229 string name = 2;
230}
231
232// DeleteVariableResponse is empty.
233message DeleteVariableResponse {}
234
235// EnvironmentService manages the environments of a repository, to which
236// secrets and variables are attached. Environments have no protection rules
237// and no deployments. Access rules and errors are those of SecretService (the
238// secrets:write scope, no token limited to branches), and the same servers
239// (feature "ci.secrets") implement it.
240service EnvironmentService {
241 // CreateEnvironment creates an environment. It succeeds and changes nothing
242 // if the environment already exists (without regard to case), as GitHub's
243 // create-or-update does. Fails with invalid_argument if the name is not
244 // valid and with not_found if the repository does not exist.
245 rpc CreateEnvironment(CreateEnvironmentRequest) returns (CreateEnvironmentResponse);
246 // ListEnvironments lists the environments of a repository, ordered by name.
247 rpc ListEnvironments(ListEnvironmentsRequest) returns (ListEnvironmentsResponse);
248 // DeleteEnvironment deletes an environment with its secrets and variables.
249 // Fails with not_found if it does not exist.
250 rpc DeleteEnvironment(DeleteEnvironmentRequest) returns (DeleteEnvironmentResponse);
251}
252
253// CreateEnvironmentRequest names the environment to create.
254message CreateEnvironmentRequest {
255 // Repo is the repository name.
256 string repo = 1;
257 // Name is the name of the environment, see Environment.name.
258 string name = 2;
259}
260
261// CreateEnvironmentResponse holds the environment.
262message CreateEnvironmentResponse {
263 // Environment is the environment, new or existing.
264 Environment environment = 1;
265}
266
267// ListEnvironmentsRequest selects a page of the environments of a repository.
268message ListEnvironmentsRequest {
269 // Repo is the repository name.
270 string repo = 1;
271 // PageSize is the maximum number of environments to return. 0 means the
272 // server default; values above the server maximum are lowered to it.
273 int32 page_size = 2;
274 // PageToken is the next_page_token of a previous response. Empty for the
275 // first page.
276 string page_token = 3;
277}
278
279// ListEnvironmentsResponse is one page of environments.
280message ListEnvironmentsResponse {
281 // Environments are the environments of this page, ordered by name.
282 repeated Environment environments = 1;
283 // NextPageToken is passed as page_token to get the next page. Empty when
284 // there is no next page.
285 string next_page_token = 2;
286}
287
288// DeleteEnvironmentRequest names the environment to delete.
289message DeleteEnvironmentRequest {
290 // Repo is the repository name.
291 string repo = 1;
292 // Name is the name of the environment, without regard to case.
293 string name = 2;
294}
295
296// DeleteEnvironmentResponse is empty.
297message DeleteEnvironmentResponse {}