···9797 if p.ctx.Authorizer == nil {
9898 return nil // No authorization check if authorizer not configured
9999 }
100100+101101+ fmt.Printf("[checkWriteAccess] Checking write access for userDID=%s to holdDID=%s\n", p.ctx.DID, p.ctx.HoldDID)
100102 allowed, err := p.ctx.Authorizer.CheckWriteAccess(ctx, p.ctx.HoldDID, p.ctx.DID)
101103 if err != nil {
104104+ fmt.Printf("[checkWriteAccess] Authorization check error: %v\n", err)
102105 return fmt.Errorf("authorization check failed: %w", err)
103106 }
104107 if !allowed {
108108+ fmt.Printf("[checkWriteAccess] Write access DENIED for userDID=%s to holdDID=%s\n", p.ctx.DID, p.ctx.HoldDID)
105109 return fmt.Errorf("write access denied to hold %s", p.ctx.HoldDID)
106110 }
111111+ fmt.Printf("[checkWriteAccess] Write access ALLOWED for userDID=%s to holdDID=%s\n", p.ctx.DID, p.ctx.HoldDID)
107112 return nil
108113}
109114
+9
pkg/auth/hold_authorizer.go
···5555// - Must be authenticated
5656// - Must be hold owner OR crew member
5757func CheckWriteAccessWithCaptain(captain *atproto.CaptainRecord, userDID string, isCrew bool) bool {
5858+ fmt.Printf("[CheckWriteAccessWithCaptain] userDID=%s captain.Owner=%s isCrew=%v\n", userDID, captain.Owner, isCrew)
5959+5860 if userDID == "" {
5961 // Anonymous writes not allowed
6262+ fmt.Printf("[CheckWriteAccessWithCaptain] DENIED: Anonymous user\n")
6063 return false
6164 }
62656366 // Check if DID is the hold owner
6467 if userDID == captain.Owner {
6568 // Owner always has write access
6969+ fmt.Printf("[CheckWriteAccessWithCaptain] ALLOWED: User is hold owner\n")
6670 return true
6771 }
68726973 // Check if DID is a crew member
7474+ if isCrew {
7575+ fmt.Printf("[CheckWriteAccessWithCaptain] ALLOWED: User is crew member\n")
7676+ } else {
7777+ fmt.Printf("[CheckWriteAccessWithCaptain] DENIED: User is not owner or crew\n")
7878+ }
7079 return isCrew
7180}
7281
+6
pkg/auth/hold_remote.go
···265265266266 // Check approval cache first (15min TTL)
267267 if approved, err := a.getCachedApproval(holdDID, userDID); err == nil && approved {
268268+ fmt.Printf("[IsCrewMember] Using cached APPROVAL: holdDID=%s userDID=%s\n", holdDID, userDID)
268269 return true, nil
269270 }
270271271272 // Check denial cache with backoff
272273 if blocked, err := a.isBlockedByDenialBackoff(holdDID, userDID); err == nil && blocked {
273274 // Still in backoff period - don't query again
275275+ fmt.Printf("[IsCrewMember] BLOCKED by denial backoff cache: holdDID=%s userDID=%s\n", holdDID, userDID)
274276 return false, nil
275277 }
276278277279 // Cache miss or expired - query XRPC endpoint
280280+ fmt.Printf("[IsCrewMember] Cache miss, querying hold: holdDID=%s userDID=%s\n", holdDID, userDID)
278281 isCrew, err := a.isCrewMemberNoCache(ctx, holdDID, userDID)
279282 if err != nil {
283283+ fmt.Printf("[IsCrewMember] Query error: %v\n", err)
280284 return false, err
281285 }
282286283287 // Update cache based on result
284288 if isCrew {
285289 // Cache approval for 15 minutes
290290+ fmt.Printf("[IsCrewMember] Query result: APPROVED, caching for 15min\n")
286291 _ = a.cacheApproval(holdDID, userDID, 15*time.Minute)
287292 } else {
288293 // Cache denial with exponential backoff
294294+ fmt.Printf("[IsCrewMember] Query result: DENIED, caching with backoff\n")
289295 _ = a.cacheDenial(holdDID, userDID)
290296 }
291297