Skip to content

Commit 210b710

Browse files
Add AuthService proto definition with token management
Define AuthService with five RPC operations: - CreateToken and RevokeToken for token lifecycle management - CreateSetupCode and ExchangeSetupCode for secure credential distribution - ListTokens for metadata retrieval Includes message definitions with buf/validate constraints and generated Connect protocol Go bindings. Co-authored-by: construct-agent <noreply@construct.sh>
1 parent 1380980 commit 210b710

4 files changed

Lines changed: 1263 additions & 1 deletion

File tree

api/def/construct/v1/auth.proto

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
syntax = "proto3";
2+
3+
package construct.v1;
4+
5+
import "buf/validate/validate.proto";
6+
import "construct/v1/common.proto";
7+
import "google/protobuf/duration.proto";
8+
import "google/protobuf/timestamp.proto";
9+
10+
option go_package = "github.com/furisto/construct/api/go/v1";
11+
12+
// AuthService handles authentication operations including token management
13+
// and credential exchange flows.
14+
//
15+
// Token management operations (Create, List, Revoke) require admin privileges,
16+
// which are granted implicitly to connections over Unix sockets or explicitly
17+
// via tokens with admin scope.
18+
service AuthService {
19+
// CreateToken generates a new authentication token.
20+
//
21+
// The plaintext token is returned only once in the response and cannot be
22+
// retrieved again.
23+
rpc CreateToken(CreateTokenRequest) returns (CreateTokenResponse);
24+
25+
// CreateSetupCode generates a short-lived, single-use code that can be
26+
// exchanged for a token via ExchangeSetupCode.
27+
//
28+
// Setup codes are designed for secure token distribution and expire quickly (default 15 minutes).
29+
rpc CreateSetupCode(CreateSetupCodeRequest) returns (CreateSetupCodeResponse);
30+
31+
// ListTokens returns metadata about all tokens.
32+
//
33+
// Token values are never returned, only metadata such as name, creation time,
34+
// expiration, and last usage.
35+
rpc ListTokens(ListTokensRequest) returns (ListTokensResponse);
36+
37+
// RevokeToken invalidates a token by name, preventing further use.
38+
rpc RevokeToken(RevokeTokenRequest) returns (RevokeTokenResponse);
39+
40+
// ExchangeSetupCode exchanges a setup code for an authentication token.
41+
//
42+
// This is the only unauthenticated endpoint in the auth service. It allows
43+
// clients to obtain credentials using a short-lived setup code generated
44+
// by an admin via CreateSetupCode.
45+
//
46+
// Setup codes are single-use and automatically invalidated after successful
47+
// exchange or expiration.
48+
rpc ExchangeSetupCode(ExchangeSetupCodeRequest) returns (ExchangeSetupCodeResponse);
49+
}
50+
51+
// CreateTokenRequest contains parameters for creating a new token.
52+
message CreateTokenRequest {
53+
// Human-readable name for the token. Must be unique.
54+
// Used for identification in listings and revocation.
55+
// Example: "macbook-thomas", "ci-pipeline"
56+
string name = 1 [
57+
(buf.validate.field).string.min_len = 1,
58+
(buf.validate.field).string.max_len = 255
59+
];
60+
61+
// How long until the token expires. Default: 90 days.
62+
// Maximum allowed value is 365 days.
63+
optional google.protobuf.Duration expires_in = 2;
64+
65+
// Optional description for the token's intended use.
66+
optional string description = 3 [(buf.validate.field).string.max_len = 2048];
67+
}
68+
69+
// CreateTokenResponse contains the newly created token.
70+
message CreateTokenResponse {
71+
// The plaintext token value. This is the only time this value is available;
72+
// it is not stored and cannot be retrieved again.
73+
//
74+
// Format: "ct_<base64url-encoded-random-bytes>"
75+
// The "ct_" prefix identifies Construct tokens in logs and configurations.
76+
string token = 1 [
77+
(buf.validate.field).string.min_len = 1,
78+
(buf.validate.field).string.max_len = 255
79+
];
80+
81+
// When the token will expire.
82+
google.protobuf.Timestamp expires_at = 2 [(buf.validate.field).required = true];
83+
}
84+
85+
// CreateSetupCodeRequest contains parameters for creating a setup code.
86+
message CreateSetupCodeRequest {
87+
// Name for the token that will be created when the code is exchanged.
88+
// Must be unique at the time of exchange.
89+
string token_name = 1 [
90+
(buf.validate.field).string.min_len = 1,
91+
(buf.validate.field).string.max_len = 255
92+
];
93+
94+
// How long until the setup code expires. Default: 5 minutes.
95+
// Maximum allowed value is 3 days.
96+
optional google.protobuf.Duration expires_in = 2;
97+
98+
// How long the resulting token should be valid. Default: 90 days.
99+
optional google.protobuf.Duration token_expires_in = 3;
100+
}
101+
102+
// CreateSetupCodeResponse contains the generated setup code.
103+
message CreateSetupCodeResponse {
104+
// Short, human-readable setup code. Format: "XXXX-XXXX"
105+
string setup_code = 1 [
106+
(buf.validate.field).string.min_len = 1,
107+
(buf.validate.field).string.max_len = 9,
108+
(buf.validate.field).string.pattern = "^[A-Z0-9]{4}-[A-Z0-9]{4}$"
109+
];
110+
111+
// When the setup code expires (typically 15 minutes).
112+
google.protobuf.Timestamp expires_at = 2 [(buf.validate.field).required = true];
113+
}
114+
115+
// ListTokensRequest contains optional filters for listing tokens.
116+
message ListTokensRequest {
117+
// Optional: filter by name prefix.
118+
string name_prefix = 1;
119+
120+
// Optional: include expired tokens in results. Default: false.
121+
bool include_expired = 2;
122+
}
123+
124+
// ListTokensResponse contains token metadata.
125+
message ListTokensResponse {
126+
repeated TokenInfo tokens = 1;
127+
}
128+
129+
// TokenInfo contains metadata about a token
130+
message TokenInfo {
131+
// Unique identifier for the token.
132+
string id = 1 [(buf.validate.field).string.uuid = true];
133+
134+
// Human-readable name.
135+
string name = 2 [
136+
(buf.validate.field).string.min_len = 1,
137+
(buf.validate.field).string.max_len = 255
138+
];
139+
140+
// Optional description.
141+
optional string description = 3 [(buf.validate.field).string.max_len = 2048];
142+
143+
// When the token was created.
144+
google.protobuf.Timestamp created_at = 4 [(buf.validate.field).required = true];
145+
146+
// When the token expires.
147+
google.protobuf.Timestamp expires_at = 5 [(buf.validate.field).required = true];
148+
149+
// Whether the token is currently valid (not expired, not revoked).
150+
bool is_active = 7 [(buf.validate.field).required = true];
151+
}
152+
153+
// RevokeTokenRequest identifies the token to revoke.
154+
message RevokeTokenRequest {
155+
// Name of the token to revoke.
156+
string id = 1 [(buf.validate.field).string.uuid = true];
157+
}
158+
159+
// RevokeTokenResponse confirms the revocation.
160+
message RevokeTokenResponse {
161+
}
162+
163+
// ExchangeSetupCodeRequest contains the setup code to exchange.
164+
message ExchangeSetupCodeRequest {
165+
// Format: "XXXX-XXXX"
166+
string setup_code = 1 [
167+
(buf.validate.field).string.min_len = 1,
168+
(buf.validate.field).string.max_len = 9,
169+
(buf.validate.field).string.pattern = "^[A-Z0-9]{4}-[A-Z0-9]{4}$"
170+
];
171+
}
172+
173+
// ExchangeSetupCodeResponse contains the token issued in exchange.
174+
message ExchangeSetupCodeResponse {
175+
// The plaintext token value.
176+
string token = 1 [
177+
(buf.validate.field).string.min_len = 1,
178+
(buf.validate.field).string.max_len = 255
179+
];
180+
181+
// When the token expires.
182+
google.protobuf.Timestamp expires_at = 2 [(buf.validate.field).required = true];
183+
184+
// The token name (as specified when the setup code was created).
185+
string name = 3 [
186+
(buf.validate.field).string.min_len = 1,
187+
(buf.validate.field).string.max_len = 255
188+
];
189+
}

api/def/construct/v1/task.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ message SubscribeRequest {
239239
message TaskEvent {
240240
// task_id is the ID of the task that changed
241241
string task_id = 1 [(buf.validate.field).string.uuid = true];
242-
242+
243243
// timestamp when the event occurred
244244
google.protobuf.Timestamp timestamp = 2 [(buf.validate.field).required = true];
245245
}

0 commit comments

Comments
 (0)