token

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Mar 27, 2026 License: MIT Imports: 21 Imported by: 0

README

Token Package

Purpose & Responsibilities

The token package provides comprehensive token lifecycle management for the LLM Proxy. It handles:

  • Secure token generation using UUIDv7 (time-ordered)
  • Token validation with caching for performance
  • Token expiration and automatic revocation
  • Per-token rate limiting (in-memory and distributed)
  • Usage tracking and statistics
  • Token revocation (individual and bulk)

Architecture

graph TB
    subgraph Token["Token Package"]
        M[Manager]
        V[Validator]
        CV[CachedValidator]
        R[Revoker]
        G[TokenGenerator]
        RL[RateLimiter]
    end
    
    subgraph Storage
        TS[TokenStore]
        DB[(Database)]
        Redis[(Redis)]
    end
    
    M --> V
    M --> R
    M --> G
    M --> RL
    V --> TS
    CV --> V
    CV --> |FIFO Cache| CV
    TS --> DB
    RL --> Redis

Token Lifecycle

stateDiagram-v2
    [*] --> Generated: GenerateToken()
    Generated --> Active: CreateToken()
    Active --> Active: ValidateToken()
    Active --> RateLimited: MaxRequests reached
    Active --> Expired: ExpiresAt passed
    Active --> Revoked: RevokeToken()
    RateLimited --> Active: ResetUsage()
    Expired --> [*]: Cleanup
    Revoked --> [*]: DeleteToken()

Key Types & Interfaces

Type Description
Manager Unified interface for all token operations
TokenData Core token data structure with all properties
TokenValidator Interface for token validation
TokenStore Interface for token persistence
CachedValidator Validator with in-memory caching
Revoker Handles token revocation operations
TokenGenerator Generates secure tokens with options
TokenData Properties
Field Type Description
Token string The token ID (sk-...)
ProjectID string Associated project ID
ExpiresAt *time.Time Expiration time (nil = no expiration)
IsActive bool Active status
RequestCount int Number of requests made
MaxRequests *int Maximum requests allowed (nil = unlimited)
CacheHitCount int Number of cache hits

Token Generation

Tokens use UUIDv7 which includes a timestamp component, making them time-ordered:

  • Format: sk- prefix + base64url-encoded UUIDv7 (22 chars)
  • Example: sk-AYB2gH5xQZ1234567890ab
  • Benefits: Sortable by creation time, globally unique, URL-safe

Validation Flow

sequenceDiagram
    participant Client
    participant CachedValidator
    participant Cache
    participant Validator
    participant Store

    Client->>CachedValidator: ValidateToken(token)
    CachedValidator->>Cache: Lookup
    alt Cache Hit
        Cache-->>CachedValidator: TokenData
        CachedValidator-->>Client: ProjectID
    else Cache Miss
        CachedValidator->>Validator: ValidateToken(token)
        Validator->>Store: GetTokenByID(token)
        Store-->>Validator: TokenData
        Validator-->>CachedValidator: ProjectID
        CachedValidator->>Cache: Store
        CachedValidator-->>Client: ProjectID
    end
Validation Errors
Error Cause
ErrTokenNotFound Token doesn't exist in store
ErrTokenInactive Token has been deactivated
ErrTokenExpired Token past expiration time
ErrTokenRateLimit MaxRequests reached
ErrInvalidTokenFormat Token string malformed

Rate Limiting

graph LR
    subgraph "Rate Limiting Options"
        IM[In-Memory Limiter]
        RD[Redis Limiter]
    end
    
    subgraph "Use Cases"
        SI[Single Instance]
        MI[Multi Instance]
    end
    
    SI --> IM
    MI --> RD
    
    RD --> |Fallback| IM
Rate Limiter Types
Type Use Case State
MemoryRateLimiter Single instance In-process
RedisRateLimiter Multi-instance Distributed

See Distributed Rate Limiting Documentation for more details.

Configuration

Cache Configuration
Option Description Default
TTL Time-to-live for cache entries 5 minutes
MaxSize Maximum number of cached entries 1000
EnableCleanup Enable automatic cache cleanup true
CleanupInterval Interval between cleanup runs 1 minute
Rate Limiter Configuration
Option Description Default
KeyPrefix Redis key prefix ratelimit:
DefaultWindowDuration Rate limit window 1 minute
DefaultMaxRequests Requests per window 60
EnableFallback Fall back on Redis errors true

Testing Guidance

  • Implement TokenStore interface for mocking
  • Use in-memory database for integration tests
  • See *_test.go files for comprehensive test patterns
  • Test error conditions: not found, inactive, expired, rate limited

Troubleshooting

Common Errors
Error Cause Solution
ErrTokenNotFound Token doesn't exist Verify token was created
ErrTokenInactive Token deactivated Check if token was revoked
ErrTokenExpired Token past expiration Create new token
ErrTokenRateLimit MaxRequests reached Increase limit or reset usage
ErrInvalidTokenFormat Malformed token Check prefix and length
Cache Issues
Symptom Cause Solution
Stale data after update Cache TTL Reduce TTL or clear cache
High memory usage Large cache Reduce MaxSize
Slow validation Cache misses Increase MaxSize or TTL
Rate Limiting Issues
Symptom Cause Solution
Inconsistent limits In-memory limiter Switch to Redis limiter
Redis errors Connection issues Enable fallback mode
Limit not enforced MaxRequests is nil Set MaxRequests on token
Package Relationship
database Token persistence layer
proxy Uses TokenValidator interface
server Token management API

Files

File Description
token.go Token generation and format validation
validate.go StandardValidator implementation
cache.go CachedValidator with FIFO cache
manager.go Unified Manager interface
ratelimit.go In-memory rate limiter
redis_ratelimit.go Distributed Redis rate limiter
redis_adapter.go Redis client adapter
revoke.go Token revocation operations
expiration.go Expiration checking and auto-revoke
utils.go Helper functions (obfuscation, info)

Documentation

Index

Constants

View Source
const (
	OneHour      = time.Hour
	OneDay       = 24 * time.Hour
	OneWeek      = 7 * 24 * time.Hour
	ThirtyDays   = 30 * 24 * time.Hour
	NinetyDays   = 90 * 24 * time.Hour
	NoExpiration = time.Duration(0)
	MaxDuration  = time.Duration(1<<63 - 1)
)

Common expiration durations

View Source
const (
	// TokenPrefix is the prefix for all tokens
	TokenPrefix = "sk-"

	// TokenRegex is the regular expression for validating token format
	TokenRegexPattern = `^sk-[A-Za-z0-9_-]{22}$`
)
View Source
const (
	// MinTokenLength is the minimum acceptable token length
	MinTokenLength = 20

	// DefaultTokenExpiration is the default expiration for tokens (30 days)
	DefaultTokenExpiration = 30 * 24 * time.Hour

	// DefaultMaxRequests is the default maximum requests per token (unlimited)
	DefaultMaxRequests = 0 // 0 means unlimited
)

Constants for token options and generation

Variables

View Source
var (
	// ErrInvalidDuration is returned when an expiration duration is invalid
	ErrInvalidDuration = errors.New("invalid duration")

	// ErrExpirationInPast is returned when an expiration time is in the past
	ErrExpirationInPast = errors.New("expiration time is in the past")
)
View Source
var (
	// ErrRateLimitExceeded is returned when a token exceeds its rate limit
	ErrRateLimitExceeded = errors.New("rate limit exceeded")

	// ErrLimitOperation is returned when an operation on rate limits fails
	ErrLimitOperation = errors.New("limit operation failed")
)
View Source
var (
	// TokenRegex is the compiled regular expression for token format validation
	TokenRegex = regexp.MustCompile(TokenRegexPattern)

	// ErrInvalidTokenFormat is returned when the token format is invalid
	ErrInvalidTokenFormat = errors.New("invalid token format")

	// ErrTokenDecodingFailed is returned when the token cannot be decoded
	ErrTokenDecodingFailed = errors.New("token decoding failed")
)
View Source
var (
	ErrTokenNotFound  = errors.New("token not found")
	ErrTokenInactive  = errors.New("token is inactive")
	ErrTokenExpired   = errors.New("token has expired")
	ErrTokenRateLimit = errors.New("token has reached rate limit")
)

Errors related to token validation

View Source
var ErrRedisUnavailable = errors.New("redis unavailable for rate limiting")

ErrRedisUnavailable is returned when Redis is unavailable and fallback is disabled

View Source
var (
	// ErrTokenAlreadyRevoked is returned when trying to revoke an already revoked token
	ErrTokenAlreadyRevoked = errors.New("token is already revoked")
)

Functions

func CalculateExpiration

func CalculateExpiration(duration time.Duration) *time.Time

CalculateExpiration returns an expiration time based on the current time and the provided duration. If duration is 0 or negative, it returns nil (no expiration).

func CalculateExpirationFrom

func CalculateExpirationFrom(startTime time.Time, duration time.Duration) *time.Time

CalculateExpirationFrom returns an expiration time based on the provided start time and duration. If duration is 0 or negative, it returns nil (no expiration).

func DecodeToken

func DecodeToken(token string) (uuid.UUID, error)

DecodeToken extracts the UUID from a token string.

func ExpiresWithin

func ExpiresWithin(expiresAt *time.Time, duration time.Duration) bool

ExpiresWithin checks if the token will expire within the given duration. If expiresAt is nil, it returns false (never expires).

func ExtractTokenFromHeader

func ExtractTokenFromHeader(header string) (string, bool)

ExtractTokenFromHeader extracts a token from an HTTP Authorization header

func ExtractTokenFromRequest

func ExtractTokenFromRequest(r *http.Request) (string, bool)

ExtractTokenFromRequest extracts a token from an HTTP request

func FormatExpirationTime

func FormatExpirationTime(expiresAt *time.Time) string

FormatExpirationTime returns a human-readable string for the expiration time. If expiresAt is nil, it returns "Never expires".

func FormatTokenInfo

func FormatTokenInfo(token TokenData) string

FormatTokenInfo formats token information as a human-readable string

func GenerateRandomKey

func GenerateRandomKey(length int) (string, error)

GenerateRandomKey generates a random string suitable for use as an API key

func GenerateToken

func GenerateToken() (string, error)

GenerateToken generates a new token with the provided prefix and a UUIDv7. The UUIDv7 includes the current timestamp, making tokens time-ordered.

func IsExpired

func IsExpired(expiresAt *time.Time) bool

IsExpired checks if a token with the given expiration time is expired. If expiresAt is nil, the token never expires.

func ObfuscateToken

func ObfuscateToken(token string) string

ObfuscateToken partially obfuscates a token for display purposes

func TimeUntilExpiration

func TimeUntilExpiration(expiresAt *time.Time) time.Duration

TimeUntilExpiration returns the duration until the token expires. If expiresAt is nil, it returns the max possible duration (effectively "never").

func TruncateToken

func TruncateToken(token string, showChars int) string

TruncateToken truncates a token string for display, preserving the prefix and suffix

func ValidateExpiration

func ValidateExpiration(expiresAt *time.Time) error

ValidateExpiration checks if the given expiration time is valid (nil or in the future).

func ValidateToken

func ValidateToken(ctx context.Context, validator TokenValidator, tokenID string) (string, error)

ValidateTokenFormat checks if a token string has the correct format

func ValidateTokenFormat

func ValidateTokenFormat(token string) error

ValidateTokenFormat checks if the given token string follows the expected format. It does not check if the token exists or is valid in the database.

func ValidateTokenWithTracking

func ValidateTokenWithTracking(ctx context.Context, validator TokenValidator, tokenID string) (string, error)

ValidateTokenWithTracking validates a token and tracks its usage

Types

type AutomaticRevocation

type AutomaticRevocation struct {
	// contains filtered or unexported fields
}

AutomaticRevocation sets up periodic revocation of expired tokens

func NewAutomaticRevocation

func NewAutomaticRevocation(revoker *Revoker, interval time.Duration, logger *zap.Logger) *AutomaticRevocation

NewAutomaticRevocation creates a new automatic token revocation

func (*AutomaticRevocation) Start

func (a *AutomaticRevocation) Start()

Start begins the automatic revocation of expired tokens

func (*AutomaticRevocation) Stop

func (a *AutomaticRevocation) Stop()

Stop halts the automatic revocation

type CacheEntry

type CacheEntry struct {
	Data       TokenData
	ValidUntil time.Time
}

CacheEntry represents a cached token data with expiration

type CacheOptions

type CacheOptions struct {
	// Time-to-live for cache entries (default: 5 minutes)
	TTL time.Duration

	// Maximum size of the cache (default: 1000)
	MaxSize int

	// Whether to enable automatic cache cleanup (default: true)
	EnableCleanup bool

	// Interval for cache cleanup (default: 1 minute)
	CleanupInterval time.Duration
}

CacheOptions defines the options for the token cache

func DefaultCacheOptions

func DefaultCacheOptions() CacheOptions

DefaultCacheOptions returns the default cache options

type CachedValidator

type CachedValidator struct {
	// contains filtered or unexported fields
}

CachedValidator wraps a TokenValidator with caching

func NewCachedValidator

func NewCachedValidator(validator TokenValidator, options ...CacheOptions) *CachedValidator

NewCachedValidator creates a new validator with caching

func (*CachedValidator) ClearCache

func (cv *CachedValidator) ClearCache()

ClearCache removes all entries from the cache

func (*CachedValidator) GetCacheInfo

func (cv *CachedValidator) GetCacheInfo() string

GetCacheInfo returns a formatted string with cache statistics

func (*CachedValidator) GetCacheStats

func (cv *CachedValidator) GetCacheStats() (hits, misses, evictions, size int)

GetCacheStats returns statistics about the cache

func (*CachedValidator) ValidateToken

func (cv *CachedValidator) ValidateToken(ctx context.Context, tokenID string) (string, error)

ValidateToken validates a token using the cache when possible

func (*CachedValidator) ValidateTokenWithTracking

func (cv *CachedValidator) ValidateTokenWithTracking(ctx context.Context, tokenID string) (string, error)

ValidateTokenWithTracking validates a token and tracks usage.

For cached *unlimited* tokens, we keep validation cheap by returning from the cache and enqueueing async tracking (when an aggregator is configured).

For cached *limited* tokens, we still want to avoid an extra DB read on every request. We do this by using the cached token metadata (active/expiry/project) and performing a synchronous usage increment (which is where max_requests is enforced).

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager provides a unified interface for all token operations

func NewManager

func NewManager(store ManagerStore, useCaching bool) (*Manager, error)

NewManager creates a new token manager with the given store

func (*Manager) CreateToken

func (m *Manager) CreateToken(ctx context.Context, projectID string, options TokenOptions) (TokenData, error)

CreateToken generates a new token with the specified options

func (*Manager) DeleteToken

func (m *Manager) DeleteToken(ctx context.Context, tokenID string) error

DeleteToken completely removes a token

func (*Manager) GetCacheInfo

func (m *Manager) GetCacheInfo() (string, bool)

GetCacheInfo returns information about the token validation cache if caching is enabled

func (*Manager) GetTokenInfo

func (m *Manager) GetTokenInfo(ctx context.Context, tokenID string) (*TokenInfo, error)

GetTokenInfo gets detailed information about a token

func (*Manager) GetTokenStats

func (m *Manager) GetTokenStats(ctx context.Context, tokenID string) (*TokenStats, error)

GetTokenStats gets statistics about token usage

func (*Manager) IsTokenValid

func (m *Manager) IsTokenValid(ctx context.Context, tokenID string) bool

IsTokenValid checks if a token is valid

func (*Manager) ResetTokenUsage

func (m *Manager) ResetTokenUsage(ctx context.Context, tokenID string) error

ResetTokenUsage resets the usage count for a token

func (*Manager) RevokeExpiredTokens

func (m *Manager) RevokeExpiredTokens(ctx context.Context) (int, error)

RevokeExpiredTokens revokes all expired tokens

func (*Manager) RevokeProjectTokens

func (m *Manager) RevokeProjectTokens(ctx context.Context, projectID string) (int, error)

RevokeProjectTokens revokes all tokens for a project

func (*Manager) RevokeToken

func (m *Manager) RevokeToken(ctx context.Context, tokenID string) error

RevokeToken revokes a token

func (*Manager) StartAutomaticRevocation

func (m *Manager) StartAutomaticRevocation(interval time.Duration, logger *zap.Logger) *AutomaticRevocation

StartAutomaticRevocation starts automatic revocation of expired tokens

func (*Manager) UpdateToken

func (m *Manager) UpdateToken(ctx context.Context, token TokenData) error

UpdateToken updates an existing token in the store

func (*Manager) UpdateTokenLimit

func (m *Manager) UpdateTokenLimit(ctx context.Context, tokenID string, maxRequests *int) error

UpdateTokenLimit updates the maximum allowed requests for a token

func (*Manager) ValidateToken

func (m *Manager) ValidateToken(ctx context.Context, tokenID string) (string, error)

ValidateToken validates a token without incrementing usage

func (*Manager) ValidateTokenWithTracking

func (m *Manager) ValidateTokenWithTracking(ctx context.Context, tokenID string) (string, error)

ValidateTokenWithTracking validates a token and increments usage count

func (*Manager) WithGeneratorOptions

func (m *Manager) WithGeneratorOptions(expiration time.Duration, maxRequests *int) *Manager

WithGeneratorOptions configures the token generator with new options

type ManagerStore

type ManagerStore interface {
	TokenStore
	RevocationStore
	RateLimitStore
}

ManagerStore is a composite interface for all required store operations ManagerStore embeds all store interfaces required by Manager (TokenStore, RevocationStore, RateLimitStore)

type MemoryRateLimiter

type MemoryRateLimiter struct {
	// contains filtered or unexported fields
}

MemoryRateLimiter implements in-memory rate limiting with token bucket algorithm

func NewMemoryRateLimiter

func NewMemoryRateLimiter(defaultRate float64, defaultCapacity int) *MemoryRateLimiter

NewMemoryRateLimiter creates a new in-memory rate limiter with token bucket algorithm

func (*MemoryRateLimiter) Allow

func (m *MemoryRateLimiter) Allow(tokenID string) bool

Allow checks if a request is allowed for a token

func (*MemoryRateLimiter) GetLimit

func (m *MemoryRateLimiter) GetLimit(tokenID string) (float64, int, bool)

GetLimit gets the current rate limit and capacity for a token

func (*MemoryRateLimiter) Remove

func (m *MemoryRateLimiter) Remove(tokenID string)

Remove removes rate limit data for a token

func (*MemoryRateLimiter) Reset

func (m *MemoryRateLimiter) Reset(tokenID string)

Reset resets the rate limit for a token

func (*MemoryRateLimiter) SetLimit

func (m *MemoryRateLimiter) SetLimit(tokenID string, rate float64, capacity int)

SetLimit sets the rate limit for a specific token

type RateLimitStore

type RateLimitStore interface {
	// GetTokenByID retrieves a token by its ID
	GetTokenByID(ctx context.Context, tokenID string) (TokenData, error)

	// IncrementTokenUsage increments the usage count for a token
	IncrementTokenUsage(ctx context.Context, tokenID string) error

	// ResetTokenUsage resets the usage count for a token to zero
	ResetTokenUsage(ctx context.Context, tokenID string) error

	// UpdateTokenLimit updates the maximum allowed requests for a token
	UpdateTokenLimit(ctx context.Context, tokenID string, maxRequests *int) error
}

RateLimitStore defines the interface for rate limit persistence

type RateLimiter

type RateLimiter interface {
	// AllowRequest checks if a token is within its rate limits and updates usage
	AllowRequest(ctx context.Context, tokenID string) error

	// GetRemainingRequests returns the number of remaining requests for a token
	GetRemainingRequests(ctx context.Context, tokenID string) (int, error)

	// ResetUsage resets the usage counter for a token
	ResetUsage(ctx context.Context, tokenID string) error

	// UpdateLimit updates the maximum allowed requests for a token
	UpdateLimit(ctx context.Context, tokenID string, maxRequests *int) error
}

RateLimiter defines the interface for rate limiting

type RedisGoRateLimitAdapter

type RedisGoRateLimitAdapter struct {
	Client *redis.Client
}

RedisGoRateLimitAdapter adapts go-redis/v9 Client to the RedisRateLimitClient interface.

func NewRedisGoRateLimitAdapter

func NewRedisGoRateLimitAdapter(client *redis.Client) *RedisGoRateLimitAdapter

NewRedisGoRateLimitAdapter creates a new adapter for rate limiting operations

func (*RedisGoRateLimitAdapter) Del

Del deletes a key

func (*RedisGoRateLimitAdapter) Expire

func (a *RedisGoRateLimitAdapter) Expire(ctx context.Context, key string, expiration time.Duration) error

Expire sets a TTL on a key

func (*RedisGoRateLimitAdapter) Get

Get retrieves the value of a key

func (*RedisGoRateLimitAdapter) Incr

Incr atomically increments a key and returns the new value

func (*RedisGoRateLimitAdapter) Set

func (a *RedisGoRateLimitAdapter) Set(ctx context.Context, key, value string) error

Set sets the value of a key

func (*RedisGoRateLimitAdapter) SetNX

func (a *RedisGoRateLimitAdapter) SetNX(ctx context.Context, key string, value string, expiration time.Duration) (bool, error)

SetNX sets a key only if it doesn't exist (for distributed locking)

type RedisRateLimitClient

type RedisRateLimitClient interface {
	// Incr atomically increments a key and returns the new value
	Incr(ctx context.Context, key string) (int64, error)
	// Get retrieves the value of a key
	Get(ctx context.Context, key string) (string, error)
	// Set sets the value of a key
	Set(ctx context.Context, key, value string) error
	// Expire sets a TTL on a key
	Expire(ctx context.Context, key string, expiration time.Duration) error
	// SetNX sets a key only if it doesn't exist.
	// Included for interface compatibility with eventbus.RedisClient and potential future enhancements.
	SetNX(ctx context.Context, key string, value string, expiration time.Duration) (bool, error)
	// Del deletes a key
	Del(ctx context.Context, key string) error
}

RedisRateLimitClient defines the Redis operations needed for distributed rate limiting. This is a subset of the eventbus.RedisClient interface focused on rate limiting operations.

type RedisRateLimiter

type RedisRateLimiter struct {
	// contains filtered or unexported fields
}

RedisRateLimiter implements distributed rate limiting using Redis. It uses a sliding window counter algorithm with Redis INCR for atomic operations.

func NewRedisRateLimiter

func NewRedisRateLimiter(client RedisRateLimitClient, config RedisRateLimiterConfig) *RedisRateLimiter

NewRedisRateLimiter creates a new distributed rate limiter using Redis

func (*RedisRateLimiter) Allow

func (r *RedisRateLimiter) Allow(ctx context.Context, tokenID string) (bool, error)

Allow checks if a request from the given token should be allowed. Returns true if the request is within rate limits, false otherwise.

func (*RedisRateLimiter) CheckRedisHealth

func (r *RedisRateLimiter) CheckRedisHealth(ctx context.Context) error

CheckRedisHealth performs a health check on the Redis connection

func (*RedisRateLimiter) GetRemainingRequests

func (r *RedisRateLimiter) GetRemainingRequests(ctx context.Context, tokenID string) (int, error)

GetRemainingRequests returns the number of remaining requests for a token in the current window

func (*RedisRateLimiter) IsRedisAvailable

func (r *RedisRateLimiter) IsRedisAvailable() bool

IsRedisAvailable returns whether Redis is currently available

func (*RedisRateLimiter) RemoveTokenLimit

func (r *RedisRateLimiter) RemoveTokenLimit(tokenID string)

RemoveTokenLimit removes the custom rate limit for a token (falls back to defaults)

func (*RedisRateLimiter) ResetTokenUsage

func (r *RedisRateLimiter) ResetTokenUsage(ctx context.Context, tokenID string) error

ResetTokenUsage resets the rate limit counter for a token

func (*RedisRateLimiter) SetTokenLimit

func (r *RedisRateLimiter) SetTokenLimit(tokenID string, maxRequests int, windowDuration time.Duration)

SetTokenLimit sets a custom rate limit for a specific token

type RedisRateLimiterConfig

type RedisRateLimiterConfig struct {
	// KeyPrefix is the prefix for all Redis keys used by the rate limiter
	KeyPrefix string
	// KeyHashSecret is the HMAC secret for hashing token IDs in Redis keys.
	// When set, token IDs are hashed using HMAC-SHA256 to prevent cleartext exposure.
	// This is recommended for production deployments to enhance security.
	KeyHashSecret []byte
	// DefaultWindowDuration is the default sliding window duration for rate limiting
	DefaultWindowDuration time.Duration
	// DefaultMaxRequests is the default maximum requests per window
	DefaultMaxRequests int
	// EnableFallback enables fallback to in-memory rate limiting when Redis is unavailable
	EnableFallback bool
	// FallbackRate is the rate for fallback in-memory token bucket (tokens per second)
	FallbackRate float64
	// FallbackCapacity is the capacity for fallback in-memory token bucket
	FallbackCapacity int
}

RedisRateLimiterConfig contains configuration for the Redis rate limiter

func DefaultRedisRateLimiterConfig

func DefaultRedisRateLimiterConfig() RedisRateLimiterConfig

DefaultRedisRateLimiterConfig returns default configuration

type RevocationStore

type RevocationStore interface {
	// RevokeToken disables a token by setting is_active to false
	RevokeToken(ctx context.Context, tokenID string) error

	// DeleteToken completely removes a token from storage
	DeleteToken(ctx context.Context, tokenID string) error

	// RevokeBatchTokens revokes multiple tokens at once
	RevokeBatchTokens(ctx context.Context, tokenIDs []string) (int, error)

	// RevokeProjectTokens revokes all tokens for a project
	RevokeProjectTokens(ctx context.Context, projectID string) (int, error)

	// RevokeExpiredTokens revokes all tokens that have expired
	RevokeExpiredTokens(ctx context.Context) (int, error)
}

RevocationStore defines the interface for token revocation

type Revoker

type Revoker struct {
	// contains filtered or unexported fields
}

Revoker provides methods for token revocation

func NewRevoker

func NewRevoker(store RevocationStore) *Revoker

NewRevoker creates a new token revoker with the given store

func (*Revoker) DeleteToken

func (r *Revoker) DeleteToken(ctx context.Context, tokenID string) error

DeleteToken completely removes a token from storage (hard delete)

func (*Revoker) RevokeBatchTokens

func (r *Revoker) RevokeBatchTokens(ctx context.Context, tokenIDs []string) (int, error)

RevokeBatchTokens revokes multiple tokens in a single operation

func (*Revoker) RevokeExpiredTokens

func (r *Revoker) RevokeExpiredTokens(ctx context.Context) (int, error)

RevokeExpiredTokens revokes all tokens that have expired

func (*Revoker) RevokeProjectTokens

func (r *Revoker) RevokeProjectTokens(ctx context.Context, projectID string) (int, error)

RevokeProjectTokens revokes all tokens for a project

func (*Revoker) RevokeToken

func (r *Revoker) RevokeToken(ctx context.Context, tokenID string) error

RevokeToken soft revokes a token by setting is_active to false

type StandardRateLimiter

type StandardRateLimiter struct {
	// contains filtered or unexported fields
}

StandardRateLimiter implements RateLimiter using a persistent store

func NewRateLimiter

func NewRateLimiter(store RateLimitStore) *StandardRateLimiter

NewRateLimiter creates a new StandardRateLimiter with the given store

func (*StandardRateLimiter) AllowRequest

func (r *StandardRateLimiter) AllowRequest(ctx context.Context, tokenID string) error

AllowRequest checks if a token is within its rate limits and updates usage

func (*StandardRateLimiter) GetRemainingRequests

func (r *StandardRateLimiter) GetRemainingRequests(ctx context.Context, tokenID string) (int, error)

GetRemainingRequests returns the number of remaining requests for a token

func (*StandardRateLimiter) ResetUsage

func (r *StandardRateLimiter) ResetUsage(ctx context.Context, tokenID string) error

ResetUsage resets the usage counter for a token

func (*StandardRateLimiter) UpdateLimit

func (r *StandardRateLimiter) UpdateLimit(ctx context.Context, tokenID string, maxRequests *int) error

UpdateLimit updates the maximum allowed requests for a token

type StandardValidator

type StandardValidator struct {
	// contains filtered or unexported fields
}

StandardValidator is a validator that uses a TokenStore for validation

func NewValidator

func NewValidator(store TokenStore) *StandardValidator

NewValidator creates a new StandardValidator with the given TokenStore

func (*StandardValidator) SetUsageStatsAggregator

func (v *StandardValidator) SetUsageStatsAggregator(agg *UsageStatsAggregator)

SetUsageStatsAggregator configures an async usage stats aggregator.

When set, ValidateTokenWithTracking will enqueue request_count/last_used_at updates for unlimited tokens (MaxRequests == nil or <= 0) instead of doing a synchronous DB write.

func (*StandardValidator) ValidateToken

func (v *StandardValidator) ValidateToken(ctx context.Context, tokenString string) (string, error)

ValidateToken validates a token without incrementing usage

func (*StandardValidator) ValidateTokenWithTracking

func (v *StandardValidator) ValidateTokenWithTracking(ctx context.Context, tokenString string) (string, error)

ValidateTokenWithTracking validates a token and increments its usage count

type TokenBucket

type TokenBucket struct {
	// contains filtered or unexported fields
}

TokenBucket represents a token bucket rate limiter for a specific token

type TokenData

type TokenData struct {
	ID            string     // The token ID (UUID) - used for management operations
	Token         string     // The token string (sk-...) - used for authentication
	ProjectID     string     // The associated project ID
	ExpiresAt     *time.Time // When the token expires (nil for no expiration)
	IsActive      bool       // Whether the token is active
	DeactivatedAt *time.Time // When the token was deactivated (nil if not deactivated)
	RequestCount  int        // Number of requests made with this token
	MaxRequests   *int       // Maximum number of requests allowed (nil for unlimited)
	CreatedAt     time.Time  // When the token was created
	LastUsedAt    *time.Time // When the token was last used (nil if never used)
	CacheHitCount int        // Number of cache hits for this token
}

TokenData represents the data associated with a token

func (*TokenData) IsRateLimited

func (t *TokenData) IsRateLimited() bool

IsRateLimited returns true if the token has reached its maximum number of requests

func (*TokenData) IsValid

func (t *TokenData) IsValid() bool

IsValid returns true if the token is active, not expired, and not rate limited

func (*TokenData) ValidateFormat

func (t *TokenData) ValidateFormat() error

ValidateTokenFormat checks if a token has the correct format

type TokenGenerator

type TokenGenerator struct {
	// Default expiration time for new tokens
	DefaultExpiration time.Duration

	// Default maximum requests for new tokens (nil means unlimited)
	DefaultMaxRequests *int
}

TokenGenerator is a utility for generating tokens with specific options

func NewTokenGenerator

func NewTokenGenerator() *TokenGenerator

NewTokenGenerator creates a new TokenGenerator with default options

func (*TokenGenerator) Generate

func (g *TokenGenerator) Generate() (string, error)

Generate generates a new token with default options

func (*TokenGenerator) GenerateWithOptions

func (g *TokenGenerator) GenerateWithOptions(expiration time.Duration, maxRequests *int) (string, *time.Time, *int, error)

GenerateWithOptions generates a new token with specific options

func (*TokenGenerator) WithExpiration

func (g *TokenGenerator) WithExpiration(expiration time.Duration) *TokenGenerator

WithExpiration sets the default expiration for new tokens

func (*TokenGenerator) WithMaxRequests

func (g *TokenGenerator) WithMaxRequests(maxRequests int) *TokenGenerator

WithMaxRequests sets the default maximum requests for new tokens

type TokenInfo

type TokenInfo struct {
	Token           string     `json:"token"`
	ObfuscatedToken string     `json:"obfuscated_token"`
	CreationTime    time.Time  `json:"creation_time"`
	ExpiresAt       *time.Time `json:"expires_at,omitempty"`
	IsActive        bool       `json:"is_active"`
	RequestCount    int        `json:"request_count"`
	MaxRequests     *int       `json:"max_requests,omitempty"`
	LastUsedAt      *time.Time `json:"last_used_at,omitempty"`
	TimeRemaining   string     `json:"time_remaining,omitempty"`
	IsValid         bool       `json:"is_valid"`
}

TokenInfo represents information about a token for display purposes

func GetTokenInfo

func GetTokenInfo(token TokenData) TokenInfo

GetTokenInfo creates a TokenInfo struct with token details

type TokenOptions

type TokenOptions struct {
	// Expiration duration (0 for no expiration)
	Expiration time.Duration

	// Maximum requests (nil for no limit)
	MaxRequests *int

	// Custom metadata (implementation-dependent)
	Metadata map[string]string
}

TokenOptions contains options for token creation

type TokenRateLimit

type TokenRateLimit struct {
	MaxRequests    int
	WindowDuration time.Duration
}

TokenRateLimit holds rate limit configuration for a specific token

type TokenStats

type TokenStats struct {
	Token           string
	ObfuscatedToken string
	RequestCount    int
	RemainingCount  int // -1 means unlimited
	LastUsed        *time.Time
	TimeRemaining   time.Duration // -1 means no expiration
	IsValid         bool
}

TokenStats contains statistics about token usage

type TokenStore

type TokenStore interface {
	// GetTokenByID retrieves a token by its UUID (for management operations)
	GetTokenByID(ctx context.Context, id string) (TokenData, error)

	// GetTokenByToken retrieves a token by its token string (for authentication)
	GetTokenByToken(ctx context.Context, tokenString string) (TokenData, error)

	// IncrementTokenUsage increments the usage count for a token by its token string
	IncrementTokenUsage(ctx context.Context, tokenString string) error

	// CreateToken creates a new token in the store
	CreateToken(ctx context.Context, token TokenData) error

	// UpdateToken updates an existing token
	UpdateToken(ctx context.Context, token TokenData) error

	// ListTokens retrieves all tokens from the store
	ListTokens(ctx context.Context) ([]TokenData, error)

	// GetTokensByProjectID retrieves all tokens for a project
	GetTokensByProjectID(ctx context.Context, projectID string) ([]TokenData, error)
}

TokenStore defines the interface for token storage and retrieval

type TokenValidator

type TokenValidator interface {
	// ValidateToken validates a token and returns the associated project ID
	ValidateToken(ctx context.Context, token string) (string, error)

	// ValidateTokenWithTracking validates a token, returns the project ID, and tracks usage
	ValidateTokenWithTracking(ctx context.Context, token string) (string, error)
}

TokenValidator defines the interface for token validation

type UsageStatsAggregator

type UsageStatsAggregator struct {
	// contains filtered or unexported fields
}

UsageStatsAggregator aggregates token usage events and periodically flushes them. It uses a buffered channel for non-blocking enqueue and drops events when the buffer is full.

func NewUsageStatsAggregator

func NewUsageStatsAggregator(config UsageStatsAggregatorConfig, store UsageStatsStore, logger *zap.Logger) *UsageStatsAggregator

NewUsageStatsAggregator creates a new usage stats aggregator.

func (*UsageStatsAggregator) RecordTokenUsage

func (a *UsageStatsAggregator) RecordTokenUsage(tokenString string)

RecordTokenUsage enqueues a token usage event for the given token string. This is non-blocking; if the buffer is full, the event is dropped.

func (*UsageStatsAggregator) Start

func (a *UsageStatsAggregator) Start()

Start begins the background aggregation worker.

func (*UsageStatsAggregator) Stop

Stop gracefully shuts down the aggregator, flushing any pending stats.

type UsageStatsAggregatorConfig

type UsageStatsAggregatorConfig struct {
	BufferSize    int           // Size of buffered channel (default: 1000)
	FlushInterval time.Duration // How often to flush stats (default: 5s)
	BatchSize     int           // Max events before flush (default: 100)
}

UsageStatsAggregatorConfig holds configuration for the usage stats aggregator.

func DefaultUsageStatsAggregatorConfig

func DefaultUsageStatsAggregatorConfig() UsageStatsAggregatorConfig

DefaultUsageStatsAggregatorConfig returns default config.

type UsageStatsStore

type UsageStatsStore interface {
	// IncrementTokenUsageBatch increments request_count for multiple tokens and updates last_used_at.
	// The deltas map has token strings as keys and increment values as values.
	IncrementTokenUsageBatch(ctx context.Context, deltas map[string]int, lastUsedAt time.Time) error
}

UsageStatsStore defines the interface for persisting per-token usage stats.

Implementations are expected to treat tokenID as the token string (sk-...).

Jump to

Keyboard shortcuts

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