@@ -23,8 +23,16 @@ type RepoAccessCache struct {
2323}
2424
2525type repoAccessCacheEntry struct {
26- isPrivate bool
27- knownUsers map [string ]bool // normalized login -> has push access
26+ isPrivate bool
27+ knownUsers map [string ]bool // normalized login -> has push access
28+ viewerLogin string
29+ }
30+
31+ // RepoAccessInfo captures repository metadata needed for lockdown decisions.
32+ type RepoAccessInfo struct {
33+ IsPrivate bool
34+ HasPushAccess bool
35+ ViewerLogin string
2836}
2937
3038const (
@@ -101,12 +109,11 @@ type CacheStats struct {
101109 Evictions int64
102110}
103111
104- // GetRepoAccessInfo returns the repository's privacy status and whether the
105- // specified user has push permissions. Results are cached per repository to
106- // avoid repeated GraphQL round-trips.
107- func (c * RepoAccessCache ) GetRepoAccessInfo (ctx context.Context , username , owner , repo string ) (bool , bool , error ) {
112+ // GetRepoAccessInfo returns repository access metadata for the provided user.
113+ // Results are cached per repository to avoid repeated GraphQL round-trips.
114+ func (c * RepoAccessCache ) GetRepoAccessInfo (ctx context.Context , username , owner , repo string ) (RepoAccessInfo , error ) {
108115 if c == nil {
109- return false , false , fmt .Errorf ("nil repo access cache" )
116+ return RepoAccessInfo {} , fmt .Errorf ("nil repo access cache" )
110117 }
111118
112119 key := cacheKey (owner , repo )
@@ -120,41 +127,59 @@ func (c *RepoAccessCache) GetRepoAccessInfo(ctx context.Context, username, owner
120127 entry := cacheItem .Data ().(* repoAccessCacheEntry )
121128 if cachedHasPush , known := entry .knownUsers [userKey ]; known {
122129 c .logDebug ("repo access cache hit" , "owner" , owner , "repo" , repo , "user" , username )
123- return entry .isPrivate , cachedHasPush , nil
130+ return RepoAccessInfo {
131+ IsPrivate : entry .isPrivate ,
132+ HasPushAccess : cachedHasPush ,
133+ ViewerLogin : entry .viewerLogin ,
134+ }, nil
124135 }
125136 c .logDebug ("known users cache miss" , "owner" , owner , "repo" , repo , "user" , username )
126- _ , hasPush , queryErr := c .queryRepoAccessInfo (ctx , username , owner , repo )
137+ info , queryErr := c .queryRepoAccessInfo (ctx , username , owner , repo )
127138 if queryErr != nil {
128- return false , false , queryErr
139+ return RepoAccessInfo {} , queryErr
129140 }
130- entry .knownUsers [userKey ] = hasPush
141+ entry .knownUsers [userKey ] = info .HasPushAccess
142+ entry .viewerLogin = info .ViewerLogin
143+ entry .isPrivate = info .IsPrivate
131144 c .cache .Add (key , c .ttl , entry )
132- return entry .isPrivate , entry .knownUsers [userKey ], nil
145+ return RepoAccessInfo {
146+ IsPrivate : entry .isPrivate ,
147+ HasPushAccess : entry .knownUsers [userKey ],
148+ ViewerLogin : entry .viewerLogin ,
149+ }, nil
133150 }
134151
135152 c .logDebug ("repo access cache miss" , "owner" , owner , "repo" , repo , "user" , username )
136153
137- isPrivate , hasPush , queryErr := c .queryRepoAccessInfo (ctx , username , owner , repo )
154+ info , queryErr := c .queryRepoAccessInfo (ctx , username , owner , repo )
138155 if queryErr != nil {
139- return false , false , queryErr
156+ return RepoAccessInfo {} , queryErr
140157 }
141158
142159 // Create new entry
143160 entry := & repoAccessCacheEntry {
144- knownUsers : map [string ]bool {userKey : hasPush },
145- isPrivate : isPrivate ,
161+ knownUsers : map [string ]bool {userKey : info .HasPushAccess },
162+ isPrivate : info .IsPrivate ,
163+ viewerLogin : info .ViewerLogin ,
146164 }
147165 c .cache .Add (key , c .ttl , entry )
148166
149- return entry .isPrivate , entry .knownUsers [userKey ], nil
167+ return RepoAccessInfo {
168+ IsPrivate : entry .isPrivate ,
169+ HasPushAccess : entry .knownUsers [userKey ],
170+ ViewerLogin : entry .viewerLogin ,
171+ }, nil
150172}
151173
152- func (c * RepoAccessCache ) queryRepoAccessInfo (ctx context.Context , username , owner , repo string ) (bool , bool , error ) {
174+ func (c * RepoAccessCache ) queryRepoAccessInfo (ctx context.Context , username , owner , repo string ) (RepoAccessInfo , error ) {
153175 if c .client == nil {
154- return false , false , fmt .Errorf ("nil GraphQL client" )
176+ return RepoAccessInfo {} , fmt .Errorf ("nil GraphQL client" )
155177 }
156178
157179 var query struct {
180+ Viewer struct {
181+ Login githubv4.String
182+ }
158183 Repository struct {
159184 IsPrivate githubv4.Boolean
160185 Collaborators struct {
@@ -175,7 +200,7 @@ func (c *RepoAccessCache) queryRepoAccessInfo(ctx context.Context, username, own
175200 }
176201
177202 if err := c .client .Query (ctx , & query , variables ); err != nil {
178- return false , false , fmt .Errorf ("failed to query repository access info: %w" , err )
203+ return RepoAccessInfo {} , fmt .Errorf ("failed to query repository access info: %w" , err )
179204 }
180205
181206 hasPush := false
@@ -188,7 +213,11 @@ func (c *RepoAccessCache) queryRepoAccessInfo(ctx context.Context, username, own
188213 }
189214 }
190215
191- return bool (query .Repository .IsPrivate ), hasPush , nil
216+ return RepoAccessInfo {
217+ IsPrivate : bool (query .Repository .IsPrivate ),
218+ HasPushAccess : hasPush ,
219+ ViewerLogin : string (query .Viewer .Login ),
220+ }, nil
192221}
193222
194223func cacheKey (owner , repo string ) string {
0 commit comments