Help us shape the future of Go! Take the 2026 Go Developer Survey

pat

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 10, 2026 License: AGPL-3.0 Imports: 8 Imported by: 0

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

View Source
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.

View Source
const MaxTokensPerUser = 50

MaxTokensPerUser bounds the listing page and the auth-lookup table size.

View Source
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.

View Source
const Prefix = "shithub_pat_"

Prefix is the fixed marker prepended to every minted token.

Variables

AllScopes is the canonical ordered list — drives the create-form UI and the validation list in ValidScope.

View Source
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

func EqualHash(a, b []byte) bool

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

func HasScope(held []string, required Scope) bool

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

func HashOf(raw string) ([]byte, error)

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

func LooksLike(s string) bool

LooksLike reports whether s resembles a PAT (cheap structural check). Used by URL-credential redaction in the log layer.

func Mint

func Mint() (raw string, hash []byte, prefix string, err error)

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

func NormalizeScopes(in []string) []string

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

func ValidScope(s string) bool

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

func NewDebouncer(window time.Duration) *Debouncer

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

func (d *Debouncer) Forget(tokenID int64)

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

func (d *Debouncer) ShouldTouch(tokenID int64) bool

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.

type Scope

type Scope string

Scope is a typed scope constant. The set is intentionally coarse — matches the GitHub classic-PAT model. Fine-grained per-repo scoping is a post-MVP project.

const (
	ScopeRepoRead  Scope = "repo:read"
	ScopeRepoWrite Scope = "repo:write"
	ScopeUserRead  Scope = "user:read"
	ScopeUserWrite Scope = "user:write"
	ScopeAdminRead Scope = "admin:read"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL