Documentation
¶
Overview ¶
Package pat owns personal-access-token minting, hashing, scope constants, and the auth-middleware verification path.
Format: shithub_pat_<32-char-base62>. The fixed `shithub_pat_` prefix is recognized by secret-scanning tooling and by our own log redactor — so even if someone accidentally pastes a raw token into a log line or a public PR, downstream tooling has a chance to spot it.
Index ¶
- Constants
- Variables
- func EqualHash(a, b []byte) bool
- func HasScope(held []string, required Scope) bool
- func HashOf(raw string) ([]byte, error)
- func LooksLike(s string) bool
- func Mint() (raw string, hash []byte, prefix string, err error)
- func NormalizeScopes(in []string) []string
- func ValidScope(s string) bool
- type Debouncer
- type Scope
Constants ¶
const DisplayPrefixLen = len("shithub_pat_") + 4
DisplayPrefixLen is how much of the raw token we keep for display (e.g. on the listing page). It includes the literal `shithub_pat_` plus four characters of payload, enough to disambiguate at a glance.
const MaxTokensPerUser = 50
MaxTokensPerUser bounds the listing page and the auth-lookup table size.
const PayloadLen = 32
PayloadLen is the length of the random payload (chars), not bytes. 32 base62 characters carry log2(62)*32 ≈ 190 bits of entropy — well beyond any plausible brute-force budget.
const Prefix = "shithub_pat_"
Prefix is the fixed marker prepended to every minted token.
Variables ¶
var AllScopes = []Scope{ ScopeRepoRead, ScopeRepoWrite, ScopeUserRead, ScopeUserWrite, ScopeAdminRead, }
AllScopes is the canonical ordered list — drives the create-form UI and the validation list in ValidScope.
var ErrMalformed = errors.New("pat: malformed token")
ErrMalformed is returned when the supplied string isn't a well-formed shithub PAT. Distinct from "valid format but unknown" so the auth middleware can short-circuit without touching the DB.
Functions ¶
func EqualHash ¶
EqualHash compares two stored hashes in constant time. The auth path already keys by hash via UNIQUE-index lookup, but we also expose this for any future code that compares hashes outside a DB lookup.
func HasScope ¶
HasScope reports whether held grants required. Operations that don't require a scope (browser-session callers) skip this check entirely.
repo:write implicitly grants repo:read; user:write implicitly grants user:read. We expand the implication here so callers don't have to.
func HashOf ¶
HashOf computes the canonical lookup hash for raw, after verifying the prefix and length. Use this on every middleware lookup so a malformed input never reaches the DB index.
func LooksLike ¶
LooksLike reports whether s resembles a PAT (cheap structural check). Used by URL-credential redaction in the log layer.
func Mint ¶
Mint generates a fresh raw token, its sha256 hash (for storage), and its display prefix. The raw token MUST be shown to the user exactly once and never stored.
func NormalizeScopes ¶
NormalizeScopes filters input to known scopes, deduplicates, and returns them in AllScopes order. Used by the create handler to canonicalize whatever the form submitted before it lands in the DB.
func ValidScope ¶
ValidScope reports whether s is a known scope name.
Types ¶
type Debouncer ¶
type Debouncer struct {
// contains filtered or unexported fields
}
Debouncer suppresses repeat last-used updates for a given token within a time window. The auth middleware calls ShouldTouch before issuing the DB write so 100 requests/sec hitting the same token don't burn 100 UPDATEs on user_tokens.
Eviction is a simple cap-based sweep: once the map exceeds maxEntries, we drop entries older than the window. Acceptable for our scale — bounded by the active-PAT count, not the request rate.
func NewDebouncer ¶
NewDebouncer returns a Debouncer with a 60-second default window and a 4096-entry cap. The defaults are right for our launch scale; expose as fields (NOT as constructor args) if a test needs to override them.
func (*Debouncer) Forget ¶
Forget removes tokenID from the debouncer's memory — useful when a token is revoked, so a subsequent (unauthenticated) lookup with the same id can't accidentally inherit a stale "recently touched" state.
func (*Debouncer) ShouldTouch ¶
ShouldTouch reports whether the auth middleware should issue a last-used DB write for tokenID right now. Returns true at most once per (tokenID, window) pair — subsequent calls within the window return false. Always thread-safe.