token.proto RawHistoryFolder
1// SPDX-License-Identifier: MIT
2
3syntax = "proto3";
4
5package ermite;
6
7import "google/protobuf/timestamp.proto";
8
9// Scope is a permission carried by a token. The API knows scopes only; any
10// grouping into presets is a client concern.
11enum Scope {
12 // Not set. Rejected in requests, never returned by the server.
13 SCOPE_UNSPECIFIED = 0;
14 // SCOPE_REPO_READ allows reading private repositories (public ones need no
15 // token). Wire name: repo:read.
16 SCOPE_REPO_READ = 1;
17 // SCOPE_REPO_WRITE allows pushing and creating repositories. Wire name:
18 // repo:write.
19 SCOPE_REPO_WRITE = 2;
20 // SCOPE_REPO_ADMIN allows deleting a repository and changing its visibility,
21 // description or default branch. Wire name: repo:admin.
22 SCOPE_REPO_ADMIN = 3;
23 // SCOPE_MR_WRITE allows creating, commenting on and closing merge requests.
24 // Wire name: mr:write.
25 SCOPE_MR_WRITE = 4;
26 // SCOPE_MR_MERGE allows merging merge requests whose checks allow it. Wire name:
27 // mr:merge.
28 SCOPE_MR_MERGE = 5;
29 // SCOPE_CI_WRITE allows re-running or cancelling CI runs. Wire name:
30 // ci:write.
31 SCOPE_CI_WRITE = 6;
32 // SCOPE_SECRETS_WRITE allows managing secrets, variables and environments
33 // (SecretService, VariableService, EnvironmentService), reads included. A
34 // token limited to branches is refused them even with this scope. Wire name:
35 // secrets:write.
36 SCOPE_SECRETS_WRITE = 7;
37 // SCOPE_RUNNER_REGISTER allows registering a CI runner. Wire name:
38 // runner:register.
39 SCOPE_RUNNER_REGISTER = 8;
40 // SCOPE_TOKEN_ADMIN allows creating, listing and revoking tokens. Wire name:
41 // token:admin.
42 SCOPE_TOKEN_ADMIN = 9;
43 // SCOPE_MR_REVIEW allows setting a verdict (approve, changes requested) on
44 // merge request notes. Wire name: mr:review.
45 SCOPE_MR_REVIEW = 10;
46 // SCOPE_ISSUE_WRITE allows creating, commenting on, closing and reopening
47 // issues. Wire name: issue:write.
48 SCOPE_ISSUE_WRITE = 11;
49 // SCOPE_MR_FORCE_MERGE allows merging a merge request whatever its checks
50 // say (MergeMergeRequestRequest.ignore_checks). Wire name: mr:force-merge.
51 SCOPE_MR_FORCE_MERGE = 12;
52}
53
54// Token describes a stored token. It never contains the secret nor its hash.
55message Token {
56 // Id identifies the token in ListTokens and RevokeToken. It is not the
57 // secret and cannot be used to authenticate.
58 string id = 1;
59 // Label is a human-readable name chosen at creation.
60 string label = 2;
61 // Scopes are the permissions of the token. Never empty.
62 repeated Scope scopes = 3;
63 // Repos restricts the token to these repository names. Empty means every
64 // repository.
65 repeated string repos = 4;
66 // ExpiresAt is when the token stops working. Unset means it never expires.
67 google.protobuf.Timestamp expires_at = 5;
68 // CreatedAt is when the token was created.
69 google.protobuf.Timestamp created_at = 6;
70 // LastUsedAt is when the token last authenticated a request. Unset if never
71 // used. It may lag behind the real time by a short delay.
72 google.protobuf.Timestamp last_used_at = 7;
73 // BranchPrefixes limits the branches the token may write. Each prefix ends
74 // with "/" (for example "agent/claude/"). Empty means every branch. A limited
75 // token can push, force-push and delete only branches under its prefixes; it
76 // cannot push tags or other refs, create repositories, or merge into or
77 // delete a branch outside its prefixes.
78 repeated string branch_prefixes = 8;
79}
80
81// TokenService manages stored tokens. Every RPC needs the token:admin scope.
82//
83// A token can only create tokens that are within its own limits: scopes that
84// it holds, repositories that it may access and an expiry no later than its
85// own (including its branch prefixes). The root token (ERMITE_ADMIN_TOKEN) is not a stored token and is never
86// listed.
87service TokenService {
88 // CreateToken creates a token and returns its secret. The secret is shown
89 // only in this response and cannot be retrieved later. Fails with
90 // permission_denied when the new token would exceed the caller's limits and
91 // with invalid_argument when scopes is empty or contains SCOPE_UNSPECIFIED.
92 rpc CreateToken(CreateTokenRequest) returns (CreateTokenResponse);
93 // ListTokens lists stored tokens, newest first.
94 rpc ListTokens(ListTokensRequest) returns (ListTokensResponse);
95 // RevokeToken deletes a token; it stops working immediately. Fails with
96 // not_found if the id is unknown.
97 rpc RevokeToken(RevokeTokenRequest) returns (RevokeTokenResponse);
98}
99
100// CreateTokenRequest describes the token to create.
101message CreateTokenRequest {
102 // Label is a human-readable name, for example "laptop". Not required to be
103 // unique.
104 string label = 1;
105 // Scopes are the permissions to grant. At least one is required.
106 repeated Scope scopes = 2;
107 // Repos restricts the token to these repository names. Empty means every
108 // repository.
109 repeated string repos = 3;
110 // ExpiresAt is when the token stops working. Unset means no expiry. It must
111 // be in the future.
112 google.protobuf.Timestamp expires_at = 4;
113 // BranchPrefixes limits the branches the token may write, for example
114 // "agent/claude/". Each prefix must end with "/" and be a valid branch name
115 // once the "/" is removed; at most 8 are allowed. Empty means every branch;
116 // a limited token cannot push tags or create repositories. A token that has
117 // prefixes can only create tokens whose prefixes each lie within its own.
118 // Fails with invalid_argument when a prefix is malformed.
119 repeated string branch_prefixes = 5;
120}
121
122// CreateTokenResponse holds the new token and its secret.
123message CreateTokenResponse {
124 // Token describes the created token.
125 Token token = 1;
126 // Secret is the bearer secret to present as "Authorization: Bearer <secret>".
127 // It is returned once and never stored in clear text by the server.
128 string secret = 2;
129}
130
131// ListTokensRequest selects a page of tokens.
132message ListTokensRequest {
133 // PageSize is the maximum number of tokens to return. 0 means the server
134 // default; values above the server maximum are lowered to it.
135 int32 page_size = 1;
136 // PageToken is the next_page_token of a previous response. Empty for the
137 // first page.
138 string page_token = 2;
139}
140
141// ListTokensResponse is one page of tokens.
142message ListTokensResponse {
143 // Tokens are the tokens of this page, newest first.
144 repeated Token tokens = 1;
145 // NextPageToken is passed as page_token to get the next page. Empty when
146 // there is no next page.
147 string next_page_token = 2;
148}
149
150// RevokeTokenRequest names the token to revoke.
151message RevokeTokenRequest {
152 // Id is the Token.id to revoke.
153 string id = 1;
154}
155
156// RevokeTokenResponse is empty.
157message RevokeTokenResponse {}