Documentation
¶
Overview ¶
Package toolauth provides client-side authentication for kombify desktop tools.
Desktop tools (SpeechKit, etc.) use this package to authenticate against the kombify Cloud platform via API key or device code flow. It handles token storage (OS credential store or encrypted file fallback), automatic token refresh, entitlement checking with caching, and batched usage reporting.
Index ¶
- Variables
- type APIError
- type AuthResult
- type Client
- func (c *Client) AuthenticateWithAPIKey(ctx context.Context, apiKey string) (*AuthResult, error)
- func (c *Client) GetAccessToken(ctx context.Context) (string, error)
- func (c *Client) GetEntitlements(ctx context.Context) (*Entitlements, error)
- func (c *Client) GetFeatureValue(ctx context.Context, feature string) (any, error)
- func (c *Client) HasFeature(ctx context.Context, feature string) (bool, error)
- func (c *Client) InvalidateEntitlementCache()
- func (c *Client) IsAuthenticated() bool
- func (c *Client) Logout(_ context.Context) error
- func (c *Client) PollDeviceCode(ctx context.Context, deviceCode string) (*AuthResult, error)
- func (c *Client) ReportUsage(_ context.Context, events ...UsageEvent) error
- func (c *Client) StartDeviceCodeFlow(ctx context.Context) (*DeviceCodeResponse, error)
- func (c *Client) StartUsageReporter(ctx context.Context, flushInterval time.Duration) *UsageReporter
- type Config
- type DeviceCodeResponse
- type Entitlements
- type FileStore
- type TokenPair
- type TokenStore
- type UsageEvent
- type UsageReporter
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotAuthenticated is returned when an operation requires authentication // but no token is available. ErrNotAuthenticated = fmt.Errorf("toolauth: not authenticated") // ErrAuthorizationPending is returned by PollDeviceCode when the user has // not yet completed authorization. ErrAuthorizationPending = fmt.Errorf("toolauth: authorization pending") // ErrDeviceCodeExpired is returned by PollDeviceCode when the device code // has expired before the user authorized. ErrDeviceCodeExpired = fmt.Errorf("toolauth: device code expired") )
Sentinel errors for expected conditions.
Functions ¶
This section is empty.
Types ¶
type AuthResult ¶
type AuthResult struct {
Token TokenPair `json:"token"`
Entitlements *Entitlements `json:"entitlements,omitempty"`
}
AuthResult is the outcome of a successful authentication attempt.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client authenticates desktop tools against the kombify Cloud platform. It manages token lifecycle (obtain, refresh, store) and provides access to entitlements and usage reporting.
Client is safe for concurrent use.
func New ¶
New creates a new toolauth Client. It attempts to load a previously stored token from the token store. An error is returned only if the configuration is invalid; a missing stored token is not an error.
func (*Client) AuthenticateWithAPIKey ¶
AuthenticateWithAPIKey authenticates using a pre-provisioned API key. On success the token is persisted to the token store.
func (*Client) GetAccessToken ¶
GetAccessToken returns a valid access token, refreshing it if necessary. Returns an error if the client is not authenticated.
func (*Client) GetEntitlements ¶
func (c *Client) GetEntitlements(ctx context.Context) (*Entitlements, error)
GetEntitlements fetches the tool entitlements for the authenticated user. Results are cached for 24 hours. Use InvalidateEntitlementCache to force a fresh fetch.
func (*Client) GetFeatureValue ¶
GetFeatureValue returns the raw value of a feature from the entitlements. Returns nil, nil if the feature does not exist.
func (*Client) HasFeature ¶
HasFeature checks whether the authenticated user has the named feature enabled for this tool. The entitlement cache is used if fresh, otherwise a fetch is triggered.
func (*Client) InvalidateEntitlementCache ¶
func (c *Client) InvalidateEntitlementCache()
InvalidateEntitlementCache clears the cached entitlements so the next call to GetEntitlements, HasFeature, or GetFeatureValue triggers a fresh fetch.
func (*Client) IsAuthenticated ¶
IsAuthenticated reports whether the client holds a token. This does not verify the token is still valid on the server.
func (*Client) PollDeviceCode ¶
PollDeviceCode polls the platform to check whether the user has completed the device code authorization. Returns ErrAuthorizationPending if the user has not yet authorized, or ErrDeviceCodeExpired if the code has expired.
func (*Client) ReportUsage ¶
func (c *Client) ReportUsage(_ context.Context, events ...UsageEvent) error
ReportUsage buffers usage events for asynchronous delivery. Events are held in memory until flushed by a UsageReporter. If no UsageReporter is running, events accumulate in memory without bound; callers should start a reporter for long-lived processes.
func (*Client) StartDeviceCodeFlow ¶
func (c *Client) StartDeviceCodeFlow(ctx context.Context) (*DeviceCodeResponse, error)
StartDeviceCodeFlow initiates the OAuth 2.0 device authorization flow. The caller should display VerificationURI and UserCode to the user, then poll with PollDeviceCode.
func (*Client) StartUsageReporter ¶
func (c *Client) StartUsageReporter(ctx context.Context, flushInterval time.Duration) *UsageReporter
StartUsageReporter starts a background goroutine that flushes usage events at the given interval. The reporter runs until Stop is called or the provided context is canceled.
type Config ¶
type Config struct {
// BaseURL is the kombify API base URL (e.g. "https://api.kombify.io").
BaseURL string
// ToolName identifies the tool (e.g. "speechkit").
ToolName string
// ToolVersion is the semantic version of the tool (e.g. "0.1.0").
ToolVersion string
// TokenStore provides persistent token storage. If nil, the platform
// default is used (Windows Credential Manager or encrypted file).
TokenStore TokenStore
// HTTPClient is an optional custom HTTP client. If nil, a default
// client with a 30-second timeout is used.
HTTPClient *http.Client
}
Config configures the toolauth Client.
type DeviceCodeResponse ¶
type DeviceCodeResponse struct {
DeviceCode string `json:"device_code"`
UserCode string `json:"user_code"`
VerificationURI string `json:"verification_uri"`
ExpiresIn int `json:"expires_in"`
Interval int `json:"interval"`
}
DeviceCodeResponse is returned when initiating the device code auth flow. The user must visit VerificationURI and enter UserCode to authorize the device.
type Entitlements ¶
type Entitlements struct {
Tool string `json:"tool"`
Features map[string]any `json:"features,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
}
Entitlements describes what features a tool license grants.
type FileStore ¶
type FileStore struct{}
FileStore stores tokens as AES-256-GCM encrypted JSON files. This is the fallback when the OS credential store is unavailable. Files are stored in ~/.kombify/<toolname>/token.json.
type TokenPair ¶
type TokenPair struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresAt time.Time `json:"expires_at"`
UserID string `json:"user_id"`
}
TokenPair holds the access and refresh tokens issued by the platform.
type TokenStore ¶
type TokenStore interface {
// Save persists the token pair for the given tool name.
Save(toolName string, token *TokenPair) error
// Load retrieves a previously stored token pair.
// Returns nil, nil if no token is stored.
Load(toolName string) (*TokenPair, error)
// Delete removes the stored token pair for the given tool name.
Delete(toolName string) error
}
TokenStore persists token pairs between tool sessions. Implementations must be safe for concurrent use.
func DefaultTokenStore ¶
func DefaultTokenStore() TokenStore
DefaultTokenStore returns the platform-preferred token store: the Windows Credential Manager on Windows, the encrypted file store elsewhere. Exported for native-client consumers (CLI login flows) that need direct store access without the full Client device-flow wrapper.
type UsageEvent ¶
type UsageEvent struct {
Metric string `json:"metric"`
Value float64 `json:"value"`
At time.Time `json:"at"`
}
UsageEvent represents a single usage metric to be reported to the platform.
type UsageReporter ¶
type UsageReporter struct {
// contains filtered or unexported fields
}
UsageReporter runs a background goroutine that periodically flushes buffered usage events to the platform API.
func (*UsageReporter) Stop ¶
func (r *UsageReporter) Stop()
Stop signals the reporter to flush remaining events and stop. It blocks until the final flush completes.