Address production-readiness review: clearer errors, safer votes, and ops hardening.

Distinguish auth/lookup failures, make votes idempotent on visible questions, bound shutdown, page admin users, LRU throttle, trusted-proxy CIDRs, avatar cleanup, versioned migrations, and session cleanup logging.
This commit is contained in:
2026-08-22 12:16:59 -07:00
parent 5bdaa8977f
commit 29b0536215
26 changed files with 612 additions and 146 deletions
+11 -2
View File
@@ -6,15 +6,23 @@ import "context"
const (
HuntListLimit = 100
ProfileListLimit = 50
AdminUsersLimit = 200
AdminUsersLimit = 50
)
// ListUsersQuery is a paginated admin user search.
type ListUsersQuery struct {
Search string
CursorCreated string
CursorID string
Limit int
}
// Store is the application persistence API used by the web layer.
type Store interface {
CreateUser(ctx context.Context, u *User) error
UserByID(ctx context.Context, id string) (*User, error)
UserByUsername(ctx context.Context, username string) (*User, error)
ListUsers(ctx context.Context) ([]User, error)
ListUsers(ctx context.Context, q ListUsersQuery) (users []User, nextCursorCreated, nextCursorID string, err error)
CountAdmins(ctx context.Context) (int, error)
SetUserRole(ctx context.Context, id string, role Role) error
SaveUserProfile(ctx context.Context, u *User) error
@@ -29,5 +37,6 @@ type Store interface {
GetAnswer(ctx context.Context, questionID string) (*Answer, error)
UpsertAnswer(ctx context.Context, a *Answer) error
// Vote sets the vote to 1, -1, or 0 (clear) on a visible question.
Vote(ctx context.Context, userID, questionID string, value int) error
}