+2
.gitignore
+2
.gitignore
+24
appview/oauth/client/oauth_client.go
+24
appview/oauth/client/oauth_client.go
···
1
+
package client
2
+
3
+
import (
4
+
oauth "github.com/haileyok/atproto-oauth-golang"
5
+
"github.com/haileyok/atproto-oauth-golang/helpers"
6
+
)
7
+
8
+
type OAuthClient struct {
9
+
*oauth.Client
10
+
}
11
+
12
+
func NewClient(clientId, clientJwk, redirectUri string) (*OAuthClient, error) {
13
+
k, err := helpers.ParseJWKFromBytes([]byte(clientJwk))
14
+
if err != nil {
15
+
return nil, err
16
+
}
17
+
18
+
cli, err := oauth.NewClient(oauth.ClientArgs{
19
+
ClientId: clientId,
20
+
ClientJwk: k,
21
+
RedirectUri: redirectUri,
22
+
})
23
+
return &OAuthClient{cli}, err
24
+
}
+260
appview/oauth/handler/handler.go
+260
appview/oauth/handler/handler.go
···
1
+
package oauth
2
+
3
+
import (
4
+
"encoding/json"
5
+
"fmt"
6
+
"log"
7
+
"net/http"
8
+
"net/url"
9
+
"strings"
10
+
11
+
"github.com/go-chi/chi/v5"
12
+
"github.com/gorilla/sessions"
13
+
"github.com/haileyok/atproto-oauth-golang/helpers"
14
+
"github.com/lestrrat-go/jwx/v2/jwk"
15
+
"tangled.sh/tangled.sh/core/appview"
16
+
"tangled.sh/tangled.sh/core/appview/db"
17
+
"tangled.sh/tangled.sh/core/appview/oauth"
18
+
"tangled.sh/tangled.sh/core/appview/oauth/client"
19
+
"tangled.sh/tangled.sh/core/appview/pages"
20
+
)
21
+
22
+
const (
23
+
oauthScope = "atproto transition:generic"
24
+
)
25
+
26
+
type OAuthHandler struct {
27
+
Config *appview.Config
28
+
Pages *pages.Pages
29
+
Resolver *appview.Resolver
30
+
Db *db.DB
31
+
Store *sessions.CookieStore
32
+
OAuth *oauth.OAuth
33
+
}
34
+
35
+
func (o *OAuthHandler) Router() http.Handler {
36
+
r := chi.NewRouter()
37
+
38
+
// gets mounted on /oauth
39
+
r.Get("/client-metadata.json", o.clientMetadata)
40
+
r.Get("/jwks.json", o.jwks)
41
+
r.Get("/login", o.login)
42
+
r.Post("/login", o.login)
43
+
r.Get("/callback", o.callback)
44
+
return r
45
+
}
46
+
47
+
func (o *OAuthHandler) clientMetadata(w http.ResponseWriter, r *http.Request) {
48
+
metadata := map[string]any{
49
+
"client_id": o.Config.OAuth.ServerMetadataUrl,
50
+
"client_name": "Tangled",
51
+
"subject_type": "public",
52
+
"client_uri": o.Config.Core.AppviewHost,
53
+
"redirect_uris": []string{fmt.Sprintf("%s/oauth/callback", o.Config.Core.AppviewHost)},
54
+
"grant_types": []string{"authorization_code", "refresh_token"},
55
+
"response_types": []string{"code"},
56
+
"application_type": "web",
57
+
"dpop_bound_access_tokens": true,
58
+
"jwks_uri": fmt.Sprintf("%s/oauth/jwks.json", o.Config.Core.AppviewHost),
59
+
"scope": "atproto transition:generic",
60
+
"token_endpoint_auth_method": "private_key_jwt",
61
+
"token_endpoint_auth_signing_alg": "ES256",
62
+
}
63
+
64
+
fmt.Println("clientMetadata", metadata)
65
+
66
+
w.Header().Set("Content-Type", "application/json")
67
+
w.WriteHeader(http.StatusOK)
68
+
json.NewEncoder(w).Encode(metadata)
69
+
}
70
+
71
+
func (o *OAuthHandler) jwks(w http.ResponseWriter, r *http.Request) {
72
+
jwks := o.Config.OAuth.Jwks
73
+
pubKey, err := pubKeyFromJwk(jwks)
74
+
if err != nil {
75
+
log.Printf("error parsing public key: %v", err)
76
+
http.Error(w, err.Error(), http.StatusInternalServerError)
77
+
return
78
+
}
79
+
80
+
response := helpers.CreateJwksResponseObject(pubKey)
81
+
82
+
w.Header().Set("Content-Type", "application/json")
83
+
w.WriteHeader(http.StatusOK)
84
+
json.NewEncoder(w).Encode(response)
85
+
}
86
+
87
+
// temporary until we swap out the main login page
88
+
func (o *OAuthHandler) login(w http.ResponseWriter, r *http.Request) {
89
+
switch r.Method {
90
+
case http.MethodGet:
91
+
o.Pages.OAuthLogin(w, pages.LoginParams{})
92
+
case http.MethodPost:
93
+
handle := strings.TrimPrefix(r.FormValue("handle"), "@")
94
+
95
+
resolved, err := o.Resolver.ResolveIdent(r.Context(), handle)
96
+
if err != nil {
97
+
log.Println("failed to resolve handle:", err)
98
+
o.Pages.Notice(w, "login-msg", fmt.Sprintf("\"%s\" is an invalid handle.", handle))
99
+
return
100
+
}
101
+
oauthClient, err := client.NewClient(
102
+
o.Config.OAuth.ServerMetadataUrl,
103
+
o.Config.OAuth.Jwks,
104
+
fmt.Sprintf("%s/oauth/callback", o.Config.Core.AppviewHost))
105
+
106
+
if err != nil {
107
+
log.Println("failed to create oauth client:", err)
108
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
109
+
return
110
+
}
111
+
112
+
authServer, err := oauthClient.ResolvePdsAuthServer(r.Context(), resolved.PDSEndpoint())
113
+
if err != nil {
114
+
log.Println("failed to resolve auth server:", err)
115
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
116
+
return
117
+
}
118
+
119
+
authMeta, err := oauthClient.FetchAuthServerMetadata(r.Context(), authServer)
120
+
if err != nil {
121
+
log.Println("failed to fetch auth server metadata:", err)
122
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
123
+
return
124
+
}
125
+
126
+
dpopKey, err := helpers.GenerateKey(nil)
127
+
if err != nil {
128
+
log.Println("failed to generate dpop key:", err)
129
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
130
+
return
131
+
}
132
+
133
+
dpopKeyJson, err := json.Marshal(dpopKey)
134
+
if err != nil {
135
+
log.Println("failed to marshal dpop key:", err)
136
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
137
+
return
138
+
}
139
+
140
+
parResp, err := oauthClient.SendParAuthRequest(r.Context(), authServer, authMeta, handle, oauthScope, dpopKey)
141
+
if err != nil {
142
+
log.Println("failed to send par auth request:", err)
143
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
144
+
return
145
+
}
146
+
147
+
err = db.SaveOAuthRequest(o.Db, db.OAuthRequest{
148
+
Did: resolved.DID.String(),
149
+
PdsUrl: resolved.PDSEndpoint(),
150
+
Handle: handle,
151
+
AuthserverIss: authMeta.Issuer,
152
+
PkceVerifier: parResp.PkceVerifier,
153
+
DpopAuthserverNonce: parResp.DpopAuthserverNonce,
154
+
DpopPrivateJwk: string(dpopKeyJson),
155
+
State: parResp.State,
156
+
})
157
+
if err != nil {
158
+
log.Println("failed to save oauth request:", err)
159
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
160
+
return
161
+
}
162
+
163
+
u, _ := url.Parse(authMeta.AuthorizationEndpoint)
164
+
u.RawQuery = fmt.Sprintf("client_id=%s&request_uri=%s", url.QueryEscape(o.Config.OAuth.ServerMetadataUrl), parResp.RequestUri)
165
+
o.Pages.HxRedirect(w, u.String())
166
+
}
167
+
}
168
+
169
+
func (o *OAuthHandler) callback(w http.ResponseWriter, r *http.Request) {
170
+
state := r.FormValue("state")
171
+
172
+
oauthRequest, err := db.GetOAuthRequestByState(o.Db, state)
173
+
if err != nil {
174
+
log.Println("failed to get oauth request:", err)
175
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
176
+
return
177
+
}
178
+
179
+
defer func() {
180
+
err := db.DeleteOAuthRequestByState(o.Db, state)
181
+
if err != nil {
182
+
log.Println("failed to delete oauth request for state:", state, err)
183
+
}
184
+
}()
185
+
186
+
code := r.FormValue("code")
187
+
if code == "" {
188
+
log.Println("missing code for state: ", state)
189
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
190
+
return
191
+
}
192
+
193
+
iss := r.FormValue("iss")
194
+
if iss == "" {
195
+
log.Println("missing iss for state: ", state)
196
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
197
+
return
198
+
}
199
+
200
+
oauthClient, err := client.NewClient(
201
+
o.Config.OAuth.ServerMetadataUrl,
202
+
o.Config.OAuth.Jwks,
203
+
fmt.Sprintf("%s/oauth/callback", o.Config.Core.AppviewHost))
204
+
205
+
if err != nil {
206
+
log.Println("failed to create oauth client:", err)
207
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
208
+
return
209
+
}
210
+
211
+
jwk, err := helpers.ParseJWKFromBytes([]byte(oauthRequest.DpopPrivateJwk))
212
+
if err != nil {
213
+
log.Println("failed to parse jwk:", err)
214
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
215
+
return
216
+
}
217
+
218
+
tokenResp, err := oauthClient.InitialTokenRequest(
219
+
r.Context(),
220
+
code,
221
+
oauthRequest.AuthserverIss,
222
+
oauthRequest.PkceVerifier,
223
+
oauthRequest.DpopAuthserverNonce,
224
+
jwk,
225
+
)
226
+
if err != nil {
227
+
log.Println("failed to get token:", err)
228
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
229
+
return
230
+
}
231
+
232
+
if tokenResp.Scope != oauthScope {
233
+
log.Println("scope doesn't match:", tokenResp.Scope)
234
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
235
+
return
236
+
}
237
+
238
+
err = o.OAuth.SaveSession(w, r, oauthRequest, tokenResp)
239
+
if err != nil {
240
+
log.Println("failed to save session:", err)
241
+
o.Pages.Notice(w, "login-msg", "Failed to authenticate. Try again later.")
242
+
return
243
+
}
244
+
245
+
log.Println("session saved successfully")
246
+
247
+
http.Redirect(w, r, "/", http.StatusFound)
248
+
}
249
+
250
+
func pubKeyFromJwk(jwks string) (jwk.Key, error) {
251
+
k, err := helpers.ParseJWKFromBytes([]byte(jwks))
252
+
if err != nil {
253
+
return nil, err
254
+
}
255
+
pubKey, err := k.PublicKey()
256
+
if err != nil {
257
+
return nil, err
258
+
}
259
+
return pubKey, nil
260
+
}
+206
appview/oauth/oauth.go
+206
appview/oauth/oauth.go
···
1
+
package oauth
2
+
3
+
import (
4
+
"fmt"
5
+
"log"
6
+
"net/http"
7
+
"time"
8
+
9
+
"github.com/gorilla/sessions"
10
+
oauth "github.com/haileyok/atproto-oauth-golang"
11
+
"github.com/haileyok/atproto-oauth-golang/helpers"
12
+
"tangled.sh/tangled.sh/core/appview"
13
+
"tangled.sh/tangled.sh/core/appview/db"
14
+
"tangled.sh/tangled.sh/core/appview/oauth/client"
15
+
xrpc "tangled.sh/tangled.sh/core/appview/xrpcclient"
16
+
)
17
+
18
+
type OAuthRequest struct {
19
+
ID uint
20
+
AuthserverIss string
21
+
State string
22
+
Did string
23
+
PdsUrl string
24
+
PkceVerifier string
25
+
DpopAuthserverNonce string
26
+
DpopPrivateJwk string
27
+
}
28
+
29
+
type OAuth struct {
30
+
Store *sessions.CookieStore
31
+
Db *db.DB
32
+
Config *appview.Config
33
+
}
34
+
35
+
func NewOAuth(db *db.DB, config *appview.Config) *OAuth {
36
+
return &OAuth{
37
+
Store: sessions.NewCookieStore([]byte(config.Core.CookieSecret)),
38
+
Db: db,
39
+
Config: config,
40
+
}
41
+
}
42
+
43
+
func (o *OAuth) SaveSession(w http.ResponseWriter, r *http.Request, oreq db.OAuthRequest, oresp *oauth.TokenResponse) error {
44
+
// first we save the did in the user session
45
+
userSession, err := o.Store.Get(r, appview.SessionName)
46
+
if err != nil {
47
+
return err
48
+
}
49
+
50
+
userSession.Values[appview.SessionDid] = oreq.Did
51
+
userSession.Values[appview.SessionAuthenticated] = true
52
+
err = userSession.Save(r, w)
53
+
if err != nil {
54
+
return fmt.Errorf("error saving user session: %w", err)
55
+
}
56
+
57
+
// then save the whole thing in the db
58
+
session := db.OAuthSession{
59
+
Did: oreq.Did,
60
+
Handle: oreq.Handle,
61
+
PdsUrl: oreq.PdsUrl,
62
+
DpopAuthserverNonce: oreq.DpopAuthserverNonce,
63
+
AuthServerIss: oreq.AuthserverIss,
64
+
DpopPrivateJwk: oreq.DpopPrivateJwk,
65
+
AccessJwt: oresp.AccessToken,
66
+
RefreshJwt: oresp.RefreshToken,
67
+
Expiry: time.Now().Add(time.Duration(oresp.ExpiresIn) * time.Second).Format(time.RFC3339),
68
+
}
69
+
70
+
return db.SaveOAuthSession(o.Db, session)
71
+
}
72
+
73
+
func (o *OAuth) ClearSession(r *http.Request, w http.ResponseWriter) error {
74
+
userSession, err := o.Store.Get(r, appview.SessionName)
75
+
if err != nil || userSession.IsNew {
76
+
return fmt.Errorf("error getting user session (or new session?): %w", err)
77
+
}
78
+
79
+
did := userSession.Values[appview.SessionDid].(string)
80
+
81
+
err = db.DeleteOAuthSessionByDid(o.Db, did)
82
+
if err != nil {
83
+
return fmt.Errorf("error deleting oauth session: %w", err)
84
+
}
85
+
86
+
userSession.Options.MaxAge = -1
87
+
88
+
return userSession.Save(r, w)
89
+
}
90
+
91
+
func (o *OAuth) GetSession(r *http.Request) (*db.OAuthSession, bool, error) {
92
+
userSession, err := o.Store.Get(r, appview.SessionName)
93
+
if err != nil || userSession.IsNew {
94
+
return nil, false, fmt.Errorf("error getting user session (or new session?): %w", err)
95
+
}
96
+
97
+
did := userSession.Values[appview.SessionDid].(string)
98
+
auth := userSession.Values[appview.SessionAuthenticated].(bool)
99
+
100
+
session, err := db.GetOAuthSessionByDid(o.Db, did)
101
+
if err != nil {
102
+
return nil, false, fmt.Errorf("error getting oauth session: %w", err)
103
+
}
104
+
105
+
expiry, err := time.Parse(time.RFC3339, session.Expiry)
106
+
if err != nil {
107
+
return nil, false, fmt.Errorf("error parsing expiry time: %w", err)
108
+
}
109
+
if expiry.Sub(time.Now()) <= 5*time.Minute {
110
+
privateJwk, err := helpers.ParseJWKFromBytes([]byte(session.DpopPrivateJwk))
111
+
if err != nil {
112
+
return nil, false, err
113
+
}
114
+
oauthClient, err := client.NewClient(o.Config.OAuth.ServerMetadataUrl,
115
+
o.Config.OAuth.Jwks,
116
+
fmt.Sprintf("%s/oauth/callback", o.Config.Core.AppviewHost))
117
+
118
+
if err != nil {
119
+
return nil, false, err
120
+
}
121
+
122
+
resp, err := oauthClient.RefreshTokenRequest(r.Context(), session.RefreshJwt, session.AuthServerIss, session.DpopAuthserverNonce, privateJwk)
123
+
if err != nil {
124
+
return nil, false, err
125
+
}
126
+
127
+
newExpiry := time.Now().Add(time.Duration(resp.ExpiresIn) * time.Second).Format(time.RFC3339)
128
+
err = db.RefreshOAuthSession(o.Db, did, resp.AccessToken, resp.RefreshToken, newExpiry)
129
+
if err != nil {
130
+
return nil, false, fmt.Errorf("error refreshing oauth session: %w", err)
131
+
}
132
+
133
+
// update the current session
134
+
session.AccessJwt = resp.AccessToken
135
+
session.RefreshJwt = resp.RefreshToken
136
+
session.DpopAuthserverNonce = resp.DpopAuthserverNonce
137
+
session.Expiry = newExpiry
138
+
}
139
+
140
+
return session, auth, nil
141
+
}
142
+
143
+
type User struct {
144
+
Handle string
145
+
Did string
146
+
Pds string
147
+
}
148
+
149
+
func (a *OAuth) GetUser(r *http.Request) *User {
150
+
clientSession, err := a.Store.Get(r, appview.SessionName)
151
+
152
+
if err != nil || clientSession.IsNew {
153
+
return nil
154
+
}
155
+
156
+
return &User{
157
+
Handle: clientSession.Values[appview.SessionHandle].(string),
158
+
Did: clientSession.Values[appview.SessionDid].(string),
159
+
Pds: clientSession.Values[appview.SessionPds].(string),
160
+
}
161
+
}
162
+
163
+
func (a *OAuth) GetDid(r *http.Request) string {
164
+
clientSession, err := a.Store.Get(r, appview.SessionName)
165
+
166
+
if err != nil || clientSession.IsNew {
167
+
return ""
168
+
}
169
+
170
+
return clientSession.Values[appview.SessionDid].(string)
171
+
}
172
+
173
+
func (o *OAuth) AuthorizedClient(r *http.Request) (*xrpc.Client, error) {
174
+
session, auth, err := o.GetSession(r)
175
+
if err != nil {
176
+
return nil, fmt.Errorf("error getting session: %w", err)
177
+
}
178
+
if !auth {
179
+
return nil, fmt.Errorf("not authorized")
180
+
}
181
+
182
+
client := &oauth.XrpcClient{
183
+
OnDpopPdsNonceChanged: func(did, newNonce string) {
184
+
err := db.UpdateDpopPdsNonce(o.Db, did, newNonce)
185
+
if err != nil {
186
+
log.Printf("error updating dpop pds nonce: %v", err)
187
+
}
188
+
},
189
+
}
190
+
191
+
privateJwk, err := helpers.ParseJWKFromBytes([]byte(session.DpopPrivateJwk))
192
+
if err != nil {
193
+
return nil, fmt.Errorf("error parsing private jwk: %w", err)
194
+
}
195
+
196
+
xrpcClient := xrpc.NewClient(client, &oauth.XrpcAuthedRequestArgs{
197
+
Did: session.Did,
198
+
PdsUrl: session.PdsUrl,
199
+
DpopPdsNonce: session.PdsUrl,
200
+
AccessToken: session.AccessJwt,
201
+
Issuer: session.AuthServerIss,
202
+
DpopPrivateJwk: privateJwk,
203
+
})
204
+
205
+
return xrpcClient, nil
206
+
}
+18
-12
go.mod
+18
-12
go.mod
···
1
1
module tangled.sh/tangled.sh/core
2
2
3
-
go 1.23.0
3
+
go 1.24.0
4
4
5
-
toolchain go1.23.6
5
+
toolchain go1.24.3
6
6
7
7
require (
8
8
github.com/Blank-Xu/sql-adapter v1.1.1
9
9
github.com/alecthomas/chroma/v2 v2.15.0
10
10
github.com/bluekeyes/go-gitdiff v0.8.1
11
-
github.com/bluesky-social/indigo v0.0.0-20250123072624-9e3b84fdbb20
11
+
github.com/bluesky-social/indigo v0.0.0-20250301025210-a4e0cc37e188
12
12
github.com/bluesky-social/jetstream v0.0.0-20241210005130-ea96859b93d1
13
13
github.com/casbin/casbin/v2 v2.103.0
14
14
github.com/cyphar/filepath-securejoin v0.4.1
···
19
19
github.com/go-git/go-git/v5 v5.14.0
20
20
github.com/google/uuid v1.6.0
21
21
github.com/gorilla/sessions v1.4.0
22
+
github.com/haileyok/atproto-oauth-golang v0.0.2
22
23
github.com/ipfs/go-cid v0.5.0
24
+
github.com/lestrrat-go/jwx/v2 v2.0.12
23
25
github.com/mattn/go-sqlite3 v1.14.24
24
26
github.com/microcosm-cc/bluemonday v1.0.27
25
27
github.com/resend/resend-go/v2 v2.15.0
···
41
43
github.com/casbin/govaluate v1.3.0 // indirect
42
44
github.com/cespare/xxhash/v2 v2.3.0 // indirect
43
45
github.com/cloudflare/circl v1.6.0 // indirect
44
-
github.com/davecgh/go-spew v1.1.1 // indirect
46
+
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
45
47
github.com/dlclark/regexp2 v1.11.5 // indirect
46
48
github.com/emirpasic/gods v1.18.1 // indirect
47
49
github.com/felixge/httpsnoop v1.0.4 // indirect
48
50
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
49
51
github.com/go-git/go-billy/v5 v5.6.2 // indirect
50
-
github.com/go-logr/logr v1.4.1 // indirect
52
+
github.com/go-logr/logr v1.4.2 // indirect
51
53
github.com/go-logr/stdr v1.2.2 // indirect
52
54
github.com/goccy/go-json v0.10.2 // indirect
53
55
github.com/gogo/protobuf v1.3.2 // indirect
56
+
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
54
57
github.com/gorilla/css v1.0.1 // indirect
55
58
github.com/gorilla/securecookie v1.1.2 // indirect
56
59
github.com/gorilla/websocket v1.5.1 // indirect
···
75
78
github.com/kevinburke/ssh_config v1.2.0 // indirect
76
79
github.com/klauspost/compress v1.17.9 // indirect
77
80
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
81
+
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
82
+
github.com/lestrrat-go/httpcc v1.0.1 // indirect
83
+
github.com/lestrrat-go/httprc v1.0.4 // indirect
84
+
github.com/lestrrat-go/iter v1.0.2 // indirect
85
+
github.com/lestrrat-go/option v1.0.1 // indirect
78
86
github.com/mattn/go-isatty v0.0.20 // indirect
79
87
github.com/minio/sha256-simd v1.0.1 // indirect
80
88
github.com/mr-tron/base58 v1.2.0 // indirect
···
86
94
github.com/opentracing/opentracing-go v1.2.0 // indirect
87
95
github.com/pjbgf/sha1cd v0.3.2 // indirect
88
96
github.com/pkg/errors v0.9.1 // indirect
89
-
github.com/pmezard/go-difflib v1.0.0 // indirect
90
97
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect
91
98
github.com/prometheus/client_golang v1.19.1 // indirect
92
99
github.com/prometheus/client_model v0.6.1 // indirect
93
100
github.com/prometheus/common v0.54.0 // indirect
94
101
github.com/prometheus/procfs v0.15.1 // indirect
102
+
github.com/segmentio/asm v1.2.0 // indirect
95
103
github.com/sergi/go-diff v1.3.1 // indirect
96
104
github.com/skeema/knownhosts v1.3.1 // indirect
97
105
github.com/spaolacci/murmur3 v1.1.0 // indirect
98
-
github.com/stretchr/testify v1.10.0 // indirect
99
106
github.com/xanzy/ssh-agent v0.3.3 // indirect
100
107
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect
101
108
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
102
109
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
103
-
go.opentelemetry.io/otel v1.21.0 // indirect
104
-
go.opentelemetry.io/otel/metric v1.21.0 // indirect
105
-
go.opentelemetry.io/otel/trace v1.21.0 // indirect
110
+
go.opentelemetry.io/otel v1.29.0 // indirect
111
+
go.opentelemetry.io/otel/metric v1.29.0 // indirect
112
+
go.opentelemetry.io/otel/trace v1.29.0 // indirect
106
113
go.uber.org/atomic v1.11.0 // indirect
107
114
go.uber.org/multierr v1.11.0 // indirect
108
115
go.uber.org/zap v1.26.0 // indirect
109
116
golang.org/x/crypto v0.37.0 // indirect
110
117
golang.org/x/net v0.39.0 // indirect
111
118
golang.org/x/sys v0.32.0 // indirect
112
-
golang.org/x/time v0.5.0 // indirect
119
+
golang.org/x/time v0.8.0 // indirect
113
120
google.golang.org/protobuf v1.34.2 // indirect
114
121
gopkg.in/warnings.v0 v0.1.2 // indirect
115
-
gopkg.in/yaml.v3 v3.0.1 // indirect
116
122
lukechampine.com/blake3 v1.2.1 // indirect
117
123
)
118
124
+61
-16
go.sum
+61
-16
go.sum
···
26
26
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
27
27
github.com/bluekeyes/go-gitdiff v0.8.1 h1:lL1GofKMywO17c0lgQmJYcKek5+s8X6tXVNOLxy4smI=
28
28
github.com/bluekeyes/go-gitdiff v0.8.1/go.mod h1:WWAk1Mc6EgWarCrPFO+xeYlujPu98VuLW3Tu+B/85AE=
29
-
github.com/bluesky-social/indigo v0.0.0-20250123072624-9e3b84fdbb20 h1:yHusfYYi8odoCcsI6AurU+dRWb7itHAQNwt3/Rl9Vfs=
30
-
github.com/bluesky-social/indigo v0.0.0-20250123072624-9e3b84fdbb20/go.mod h1:Qp4YqWf+AQ3TwQCxV5Ls8O2tXE55zVTGVs3zTmn7BOg=
29
+
github.com/bluesky-social/indigo v0.0.0-20250301025210-a4e0cc37e188 h1:1sQaG37xk08/rpmdhrmMkfQWF9kZbnfHm9Zav3bbSMk=
30
+
github.com/bluesky-social/indigo v0.0.0-20250301025210-a4e0cc37e188/go.mod h1:NVBwZvbBSa93kfyweAmKwOLYawdVHdwZ9s+GZtBBVLA=
31
31
github.com/bluesky-social/jetstream v0.0.0-20241210005130-ea96859b93d1 h1:CFvRtYNSnWRAi/98M3O466t9dYuwtesNbu6FVPymRrA=
32
32
github.com/bluesky-social/jetstream v0.0.0-20241210005130-ea96859b93d1/go.mod h1:WiYEeyJSdUwqoaZ71KJSpTblemUCpwJfh5oVXplK6T4=
33
33
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
···
52
52
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
53
53
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
54
54
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
55
-
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
56
55
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
56
+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
57
+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
58
+
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
59
+
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
60
+
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
57
61
github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE=
58
62
github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU=
59
63
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y=
···
82
86
github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk=
83
87
github.com/go-git/go-git/v5 v5.6.1/go.mod h1:mvyoL6Unz0PiTQrGQfSfiLFhBH1c1e84ylC2MDs4ee8=
84
88
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
85
-
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
86
-
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
89
+
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
90
+
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
87
91
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
88
92
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
89
93
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
···
91
95
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
92
96
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
93
97
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
98
+
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
99
+
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
94
100
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
95
101
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
96
102
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
···
111
117
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
112
118
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
113
119
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
120
+
github.com/haileyok/atproto-oauth-golang v0.0.2 h1:61KPkLB615LQXR2f5x1v3sf6vPe6dOXqNpTYCgZ0Fz8=
121
+
github.com/haileyok/atproto-oauth-golang v0.0.2/go.mod h1:jcZ4GCjo5I5RuE/RsAXg1/b6udw7R4W+2rb/cGyTDK8=
114
122
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
115
123
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
116
124
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
···
159
167
github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o=
160
168
github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
161
169
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
170
+
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
171
+
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
162
172
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
163
173
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
164
174
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
···
177
187
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
178
188
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
179
189
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
190
+
github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
191
+
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
192
+
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
193
+
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
194
+
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
195
+
github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8=
196
+
github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
197
+
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
198
+
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
199
+
github.com/lestrrat-go/jwx/v2 v2.0.12 h1:3d589+5w/b9b7S3DneICPW16AqTyYXB7VRjgluSDWeA=
200
+
github.com/lestrrat-go/jwx/v2 v2.0.12/go.mod h1:Mq4KN1mM7bp+5z/W5HS8aCNs5RKZ911G/0y2qUjAQuQ=
201
+
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
202
+
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
203
+
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
180
204
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
181
205
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
182
206
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
···
212
236
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
213
237
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
214
238
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
215
-
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
216
239
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
240
+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
241
+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
217
242
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0=
218
243
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
219
244
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
···
227
252
github.com/resend/resend-go/v2 v2.15.0 h1:B6oMEPf8IEQwn2Ovx/9yymkESLDSeNfLFaNMw+mzHhE=
228
253
github.com/resend/resend-go/v2 v2.15.0/go.mod h1:3YCb8c8+pLiqhtRFXTyFwlLvfjQtluxOr9HEh2BwCkQ=
229
254
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
230
-
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
231
-
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
255
+
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
256
+
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
232
257
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
258
+
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
259
+
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
233
260
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
234
261
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
235
262
github.com/sethvargo/go-envconfig v1.1.0 h1:cWZiJxeTm7AlCvzGXrEXaSTCNgip5oJepekh/BOQuog=
···
246
273
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
247
274
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
248
275
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
276
+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
277
+
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
249
278
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
250
279
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
251
280
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
281
+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
252
282
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
283
+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
284
+
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
285
+
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
253
286
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
254
287
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
255
288
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
···
270
303
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I=
271
304
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24=
272
305
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo=
273
-
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
274
-
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
275
-
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4=
276
-
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
277
-
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
278
-
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
306
+
go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
307
+
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
308
+
go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
309
+
go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
310
+
go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
311
+
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
279
312
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
280
313
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
281
314
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
···
303
336
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
304
337
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
305
338
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
339
+
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
306
340
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
307
341
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
308
342
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
···
314
348
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
315
349
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
316
350
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
351
+
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
317
352
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
318
353
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
319
354
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
···
327
362
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
328
363
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
329
364
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
365
+
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
330
366
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
331
367
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
332
368
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
···
334
370
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
335
371
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
336
372
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
373
+
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
337
374
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
338
375
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
339
376
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
···
348
385
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
349
386
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
350
387
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
388
+
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
351
389
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
352
390
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
353
391
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
···
357
395
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
358
396
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
359
397
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
398
+
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
399
+
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
360
400
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
361
401
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
362
402
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
···
364
404
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
365
405
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
366
406
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
407
+
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
408
+
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
367
409
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
368
410
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
369
411
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
···
372
414
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
373
415
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
374
416
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
417
+
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
418
+
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
375
419
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
376
420
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
377
-
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
378
-
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
421
+
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
422
+
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
379
423
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
380
424
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
381
425
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
···
389
433
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
390
434
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
391
435
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
436
+
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
392
437
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
393
438
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
394
439
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=