forked from
slices.network/quickslice
Auto-indexing service and GraphQL API for AT Protocol Records
1// Shared database type definitions
2
3import gleam/option.{type Option}
4
5/// A record stored in the database
6pub type Record {
7 Record(
8 uri: String,
9 cid: String,
10 did: String,
11 collection: String,
12 json: String,
13 indexed_at: String,
14 rkey: String,
15 )
16}
17
18/// An actor (user) stored in the database
19pub type Actor {
20 Actor(did: String, handle: String, indexed_at: String)
21}
22
23/// A lexicon schema definition
24pub type Lexicon {
25 Lexicon(id: String, json: String, created_at: String)
26}
27
28/// Collection statistics
29pub type CollectionStat {
30 CollectionStat(collection: String, count: Int)
31}
32
33/// Result of inserting a record
34pub type InsertResult {
35 /// Record was newly inserted or updated
36 Inserted
37 /// Record was skipped (duplicate CID or unchanged)
38 Skipped
39}
40
41/// Date interval for date truncation in aggregations
42pub type DateInterval {
43 Hour
44 Day
45 Week
46 Month
47}
48
49/// A field to group by with optional date truncation
50pub type GroupByField {
51 SimpleField(field: String)
52 TruncatedField(field: String, interval: DateInterval)
53}
54
55/// A jetstream activity log entry
56pub type ActivityEntry {
57 ActivityEntry(
58 id: Int,
59 timestamp: String,
60 operation: String,
61 collection: String,
62 did: String,
63 status: String,
64 error_message: Option(String),
65 event_json: String,
66 )
67}
68
69/// Activity bucket for aggregated data
70pub type ActivityBucket {
71 ActivityBucket(
72 timestamp: String,
73 create_count: Int,
74 update_count: Int,
75 delete_count: Int,
76 )
77}
78
79// ===== OAuth Enum Types =====
80
81/// OAuth 2.0 grant types
82pub type GrantType {
83 AuthorizationCode
84 RefreshToken
85 ClientCredentials
86 DeviceCode
87}
88
89/// OAuth 2.0 response types
90pub type ResponseType {
91 Code
92}
93
94/// Client authentication methods at token endpoint
95pub type ClientAuthMethod {
96 ClientSecretBasic
97 ClientSecretPost
98 PrivateKeyJwt
99 AuthNone
100}
101
102/// Client type classification
103pub type ClientType {
104 Public
105 Confidential
106}
107
108/// Token type
109pub type TokenType {
110 Bearer
111 DPoP
112}
113
114/// PKCE code challenge method
115pub type CodeChallengeMethod {
116 S256
117 Plain
118}
119
120// ===== OAuth Enum Conversion Functions =====
121
122pub fn grant_type_to_string(gt: GrantType) -> String {
123 case gt {
124 AuthorizationCode -> "authorization_code"
125 RefreshToken -> "refresh_token"
126 ClientCredentials -> "client_credentials"
127 DeviceCode -> "urn:ietf:params:oauth:grant-type:device_code"
128 }
129}
130
131pub fn grant_type_from_string(s: String) -> Option(GrantType) {
132 case s {
133 "authorization_code" -> option.Some(AuthorizationCode)
134 "refresh_token" -> option.Some(RefreshToken)
135 "client_credentials" -> option.Some(ClientCredentials)
136 "urn:ietf:params:oauth:grant-type:device_code" -> option.Some(DeviceCode)
137 _ -> option.None
138 }
139}
140
141pub fn response_type_to_string(rt: ResponseType) -> String {
142 case rt {
143 Code -> "code"
144 }
145}
146
147pub fn response_type_from_string(s: String) -> Option(ResponseType) {
148 case s {
149 "code" -> option.Some(Code)
150 _ -> option.None
151 }
152}
153
154pub fn client_auth_method_to_string(method: ClientAuthMethod) -> String {
155 case method {
156 ClientSecretBasic -> "client_secret_basic"
157 ClientSecretPost -> "client_secret_post"
158 PrivateKeyJwt -> "private_key_jwt"
159 AuthNone -> "none"
160 }
161}
162
163pub fn client_auth_method_from_string(s: String) -> Option(ClientAuthMethod) {
164 case s {
165 "client_secret_basic" -> option.Some(ClientSecretBasic)
166 "client_secret_post" -> option.Some(ClientSecretPost)
167 "private_key_jwt" -> option.Some(PrivateKeyJwt)
168 "none" -> option.Some(AuthNone)
169 _ -> option.None
170 }
171}
172
173pub fn client_type_to_string(ct: ClientType) -> String {
174 case ct {
175 Public -> "public"
176 Confidential -> "confidential"
177 }
178}
179
180pub fn client_type_from_string(s: String) -> Option(ClientType) {
181 case s {
182 "public" -> option.Some(Public)
183 "confidential" -> option.Some(Confidential)
184 _ -> option.None
185 }
186}
187
188pub fn token_type_to_string(tt: TokenType) -> String {
189 case tt {
190 Bearer -> "Bearer"
191 DPoP -> "DPoP"
192 }
193}
194
195pub fn token_type_from_string(s: String) -> Option(TokenType) {
196 case s {
197 "Bearer" -> option.Some(Bearer)
198 "DPoP" -> option.Some(DPoP)
199 _ -> option.None
200 }
201}
202
203pub fn code_challenge_method_to_string(method: CodeChallengeMethod) -> String {
204 case method {
205 S256 -> "S256"
206 Plain -> "plain"
207 }
208}
209
210pub fn code_challenge_method_from_string(
211 s: String,
212) -> Option(CodeChallengeMethod) {
213 case s {
214 "S256" -> option.Some(S256)
215 "plain" -> option.Some(Plain)
216 _ -> option.None
217 }
218}
219
220// ===== OAuth Record Types =====
221
222/// OAuth client registration
223pub type OAuthClient {
224 OAuthClient(
225 client_id: String,
226 client_secret: Option(String),
227 client_name: String,
228 redirect_uris: List(String),
229 grant_types: List(GrantType),
230 response_types: List(ResponseType),
231 scope: Option(String),
232 token_endpoint_auth_method: ClientAuthMethod,
233 client_type: ClientType,
234 created_at: Int,
235 updated_at: Int,
236 metadata: String,
237 access_token_expiration: Int,
238 refresh_token_expiration: Int,
239 require_redirect_exact: Bool,
240 registration_access_token: Option(String),
241 jwks: Option(String),
242 )
243}
244
245/// OAuth access token
246pub type OAuthAccessToken {
247 OAuthAccessToken(
248 token: String,
249 token_type: TokenType,
250 client_id: String,
251 user_id: Option(String),
252 session_id: Option(String),
253 session_iteration: Option(Int),
254 scope: Option(String),
255 created_at: Int,
256 expires_at: Int,
257 revoked: Bool,
258 dpop_jkt: Option(String),
259 )
260}
261
262/// OAuth refresh token
263pub type OAuthRefreshToken {
264 OAuthRefreshToken(
265 token: String,
266 access_token: String,
267 client_id: String,
268 user_id: String,
269 session_id: Option(String),
270 session_iteration: Option(Int),
271 scope: Option(String),
272 created_at: Int,
273 expires_at: Option(Int),
274 revoked: Bool,
275 )
276}
277
278/// Pushed Authorization Request
279pub type OAuthParRequest {
280 OAuthParRequest(
281 request_uri: String,
282 authorization_request: String,
283 client_id: String,
284 created_at: Int,
285 expires_at: Int,
286 subject: Option(String),
287 metadata: String,
288 )
289}
290
291/// DPoP nonce
292pub type OAuthDpopNonce {
293 OAuthDpopNonce(nonce: String, expires_at: Int)
294}
295
296/// Client authorization request during bridge flow
297pub type OAuthAuthRequest {
298 OAuthAuthRequest(
299 session_id: String,
300 client_id: String,
301 redirect_uri: String,
302 scope: Option(String),
303 state: Option(String),
304 code_challenge: Option(String),
305 code_challenge_method: Option(String),
306 response_type: String,
307 nonce: Option(String),
308 login_hint: Option(String),
309 created_at: Int,
310 expires_at: Int,
311 )
312}
313
314/// ATP bridge session state
315pub type OAuthAtpSession {
316 OAuthAtpSession(
317 session_id: String,
318 iteration: Int,
319 did: Option(String),
320 session_created_at: Int,
321 atp_oauth_state: String,
322 signing_key_jkt: String,
323 dpop_key: String,
324 access_token: Option(String),
325 refresh_token: Option(String),
326 access_token_created_at: Option(Int),
327 access_token_expires_at: Option(Int),
328 access_token_scopes: Option(String),
329 session_exchanged_at: Option(Int),
330 exchange_error: Option(String),
331 )
332}
333
334/// Outbound OAuth request to ATP
335pub type OAuthAtpRequest {
336 OAuthAtpRequest(
337 oauth_state: String,
338 authorization_server: String,
339 nonce: String,
340 pkce_verifier: String,
341 signing_public_key: String,
342 dpop_private_key: String,
343 created_at: Int,
344 expires_at: Int,
345 )
346}
347
348/// OAuth authorization code
349pub type OAuthAuthorizationCode {
350 OAuthAuthorizationCode(
351 code: String,
352 client_id: String,
353 user_id: String,
354 session_id: Option(String),
355 session_iteration: Option(Int),
356 redirect_uri: String,
357 scope: Option(String),
358 code_challenge: Option(String),
359 code_challenge_method: Option(CodeChallengeMethod),
360 nonce: Option(String),
361 created_at: Int,
362 expires_at: Int,
363 used: Bool,
364 )
365}