Documentation
¶
Index ¶
- Constants
- Variables
- type CachedToken
- type Client
- func (c *Client) Close() error
- func (c *Client) CreateSync(ctx context.Context, remoteURL string, cids []string) (string, error)
- func (c *Client) Delete(ctx context.Context, recordRef *corev1.RecordRef) error
- func (c *Client) DeleteBatch(ctx context.Context, recordRefs []*corev1.RecordRef) error
- func (c *Client) DeleteStream(ctx context.Context, refsCh <-chan *corev1.RecordRef) (streaming.StreamResult[emptypb.Empty], error)
- func (c *Client) DeleteSync(ctx context.Context, syncID string) error
- func (c *Client) GetSync(ctx context.Context, syncID string) (*storev1.GetSyncResponse, error)
- func (c *Client) GetVerificationInfo(ctx context.Context, cid string) (*namingv1.GetVerificationInfoResponse, error)
- func (c *Client) GetVerificationInfoByName(ctx context.Context, name string, version string) (*namingv1.GetVerificationInfoResponse, error)
- func (c *Client) List(ctx context.Context, req *routingv1.ListRequest) (<-chan *routingv1.ListResponse, error)
- func (c *Client) ListSyncs(ctx context.Context, req *storev1.ListSyncsRequest) (<-chan *storev1.ListSyncsItem, error)
- func (c *Client) ListenStream(ctx context.Context, req *eventsv1.ListenRequest) (streaming.StreamResult[eventsv1.ListenResponse], error)
- func (c *Client) Lookup(ctx context.Context, recordRef *corev1.RecordRef) (*corev1.RecordMeta, error)
- func (c *Client) LookupBatch(ctx context.Context, recordRefs []*corev1.RecordRef) ([]*corev1.RecordMeta, error)
- func (c *Client) LookupStream(ctx context.Context, refsCh <-chan *corev1.RecordRef) (streaming.StreamResult[corev1.RecordMeta], error)
- func (c *Client) Publish(ctx context.Context, req *routingv1.PublishRequest) error
- func (c *Client) Pull(ctx context.Context, recordRef *corev1.RecordRef) (*corev1.Record, error)
- func (c *Client) PullBatch(ctx context.Context, recordRefs []*corev1.RecordRef) ([]*corev1.Record, error)
- func (c *Client) PullPublicKeys(ctx context.Context, recordRef *corev1.RecordRef) ([]string, error)
- func (c *Client) PullReferrer(ctx context.Context, req *storev1.PullReferrerRequest) (<-chan *storev1.PullReferrerResponse, error)
- func (c *Client) PullSignatures(ctx context.Context, recordRef *corev1.RecordRef) ([]*signv1.Signature, error)
- func (c *Client) PullStream(ctx context.Context, refsCh <-chan *corev1.RecordRef) (streaming.StreamResult[corev1.Record], error)
- func (c *Client) Push(ctx context.Context, record *corev1.Record) (*corev1.RecordRef, error)
- func (c *Client) PushBatch(ctx context.Context, records []*corev1.Record) ([]*corev1.RecordRef, error)
- func (c *Client) PushReferrer(ctx context.Context, req *storev1.PushReferrerRequest) (*storev1.PushReferrerResponse, error)
- func (c *Client) PushStream(ctx context.Context, recordsCh <-chan *corev1.Record) (streaming.StreamResult[corev1.RecordRef], error)
- func (c *Client) Resolve(ctx context.Context, name string, version string) (*namingv1.ResolveResponse, error)
- func (c *Client) SearchCIDs(ctx context.Context, req *searchv1.SearchCIDsRequest) (streaming.StreamResult[searchv1.SearchCIDsResponse], error)
- func (c *Client) SearchRecords(ctx context.Context, req *searchv1.SearchRecordsRequest) (streaming.StreamResult[searchv1.SearchRecordsResponse], error)
- func (c *Client) SearchRouting(ctx context.Context, req *routingv1.SearchRequest) (<-chan *routingv1.SearchResponse, error)
- func (c *Client) Sign(ctx context.Context, req *signv1.SignRequest) (*signv1.SignResponse, error)
- func (c *Client) Unpublish(ctx context.Context, req *routingv1.UnpublishRequest) error
- func (c *Client) Verify(ctx context.Context, req *signv1.VerifyRequest) (*signv1.VerifyResponse, error)
- type Config
- type DeviceCodeResponse
- type DeviceFlowConfig
- type DeviceFlowError
- type DeviceFlowResult
- type DeviceTokenResponse
- type OAuthConfig
- type OAuthTokenResult
- type Option
- type TokenCache
- type TokenCacheEntry
Constants ¶
const ( DefaultEnvPrefix = "DIRECTORY_CLIENT" DefaultServerAddress = "0.0.0.0:8888" DefaultTlsSkipVerify = false )
const ( // DefaultCallbackPort is the default port for the OAuth callback server. DefaultCallbackPort = 8484 // DefaultOAuthTimeout is the default timeout for the OAuth flow. DefaultOAuthTimeout = 5 * time.Minute // DefaultOAuthScopes are the default OAuth scopes to request. DefaultOAuthScopes = "user:email,read:org" )
const ( // DefaultTokenCacheDir is the default directory for storing cached tokens (relative to home directory). // When XDG_CONFIG_HOME is set, tokens are stored at $XDG_CONFIG_HOME/dirctl instead. //nolint:gosec // G101: This is a directory path, not a credential DefaultTokenCacheDir = ".config/dirctl" // TokenCacheFile is the filename for the cached token. //nolint:gosec // G101: This is a filename, not a credential TokenCacheFile = "auth-token.json" // DefaultTokenValidityDuration is how long a token is considered valid if no expiry is set. DefaultTokenValidityDuration = 8 * time.Hour // TokenExpiryBuffer is how much time before actual expiry we consider a token expired. TokenExpiryBuffer = 5 * time.Minute )
Variables ¶
var DefaultConfig = Config{ ServerAddress: DefaultServerAddress, }
Functions ¶
This section is empty.
Types ¶
type CachedToken ¶ added in v1.0.0
type CachedToken struct {
// AccessToken is the authentication token.
AccessToken string `json:"access_token"` // #nosec G117: intentional field - for cached token
// TokenType is the token type (usually "bearer").
TokenType string `json:"token_type,omitempty"`
// Provider is the authentication provider (github, google, azure, etc.)
Provider string `json:"provider,omitempty"`
// ExpiresAt is when the token expires.
ExpiresAt time.Time `json:"expires_at,omitzero"`
// User is the authenticated username.
User string `json:"user,omitempty"`
// UserID is the provider-specific user ID.
UserID string `json:"user_id,omitempty"`
// Email is the user's email address.
Email string `json:"email,omitempty"`
// Orgs are the user's organizations/tenants/domains.
Orgs []string `json:"orgs,omitempty"`
// CreatedAt is when the token was cached.
CreatedAt time.Time `json:"created_at"`
}
CachedToken represents a cached authentication token from any provider.
type Client ¶
type Client struct {
storev1.StoreServiceClient
routingv1.RoutingServiceClient
searchv1.SearchServiceClient
storev1.SyncServiceClient
signv1.SignServiceClient
eventsv1.EventServiceClient
namingv1.NamingServiceClient
// contains filtered or unexported fields
}
func (*Client) CreateSync ¶
func (*Client) DeleteBatch ¶
DeleteBatch removes multiple records from the store in a single stream for efficiency.
func (*Client) DeleteStream ¶
func (c *Client) DeleteStream(ctx context.Context, refsCh <-chan *corev1.RecordRef) (streaming.StreamResult[emptypb.Empty], error)
DeleteStream provides efficient streaming delete operations using channels. Record references are sent as they become available and delete confirmations are returned as they're processed. This method maintains a single gRPC stream for all operations, dramatically improving efficiency.
func (*Client) GetVerificationInfo ¶ added in v1.0.0
func (c *Client) GetVerificationInfo(ctx context.Context, cid string) (*namingv1.GetVerificationInfoResponse, error)
GetVerificationInfo retrieves the verification info for a record by CID.
func (*Client) GetVerificationInfoByName ¶ added in v1.0.0
func (c *Client) GetVerificationInfoByName(ctx context.Context, name string, version string) (*namingv1.GetVerificationInfoResponse, error)
GetVerificationInfoByName retrieves the verification info for a record by name. If version is empty, the latest version is used.
func (*Client) List ¶
func (c *Client) List(ctx context.Context, req *routingv1.ListRequest) (<-chan *routingv1.ListResponse, error)
func (*Client) ListSyncs ¶
func (c *Client) ListSyncs(ctx context.Context, req *storev1.ListSyncsRequest) (<-chan *storev1.ListSyncsItem, error)
func (*Client) ListenStream ¶
func (c *Client) ListenStream(ctx context.Context, req *eventsv1.ListenRequest) (streaming.StreamResult[eventsv1.ListenResponse], error)
ListenStream streams events from the server with the specified filters.
Returns a StreamResult that provides structured channels for receiving events, errors, and completion signals.
Example - Listen to all events:
result, err := client.ListenStream(ctx, &eventsv1.ListenRequest{})
if err != nil {
return err
}
for {
select {
case resp := <-result.ResCh():
event := resp.GetEvent()
fmt.Printf("Event: %s - %s\n", event.Type, event.ResourceId)
case err := <-result.ErrCh():
return fmt.Errorf("stream error: %w", err)
case <-result.DoneCh():
return nil
case <-ctx.Done():
return ctx.Err()
}
}
Example - Filter by event type:
result, err := client.ListenStream(ctx, &eventsv1.ListenRequest{
EventTypes: []eventsv1.EventType{
eventsv1.EventType_EVENT_TYPE_RECORD_PUSHED,
eventsv1.EventType_EVENT_TYPE_RECORD_PUBLISHED,
},
})
Example - Filter by labels:
result, err := client.ListenStream(ctx, &eventsv1.ListenRequest{
LabelFilters: []string{"/skills/AI"},
})
func (*Client) Lookup ¶
func (c *Client) Lookup(ctx context.Context, recordRef *corev1.RecordRef) (*corev1.RecordMeta, error)
Lookup retrieves metadata for a record using its reference.
func (*Client) LookupBatch ¶
func (c *Client) LookupBatch(ctx context.Context, recordRefs []*corev1.RecordRef) ([]*corev1.RecordMeta, error)
LookupBatch retrieves metadata for multiple records in a single stream for efficiency.
func (*Client) LookupStream ¶
func (c *Client) LookupStream(ctx context.Context, refsCh <-chan *corev1.RecordRef) (streaming.StreamResult[corev1.RecordMeta], error)
LookupStream provides efficient streaming lookup operations using channels. Record references are sent as they become available and metadata is returned as it's processed. This method maintains a single gRPC stream for all operations, dramatically improving efficiency.
Uses sequential streaming pattern (Send → Recv → Send → Recv) which ensures strict ordering of request-response pairs.
func (*Client) Pull ¶
Pull retrieves a single record from the store using its reference. This is a convenience wrapper around PullBatch for single-record operations.
func (*Client) PullBatch ¶
func (c *Client) PullBatch(ctx context.Context, recordRefs []*corev1.RecordRef) ([]*corev1.Record, error)
PullBatch retrieves multiple records in a single stream for efficiency. This is a convenience method that accepts a slice and returns a slice, built on top of the streaming implementation for consistency.
func (*Client) PullPublicKeys ¶ added in v1.1.0
PullPublicKeys fetches all public key referrers for a record.
func (*Client) PullReferrer ¶
func (c *Client) PullReferrer(ctx context.Context, req *storev1.PullReferrerRequest) (<-chan *storev1.PullReferrerResponse, error)
PullReferrer retrieves all referrers using the PullReferrer RPC.
func (*Client) PullSignatures ¶ added in v1.1.0
func (c *Client) PullSignatures(ctx context.Context, recordRef *corev1.RecordRef) ([]*signv1.Signature, error)
PullSignatures fetches all signature referrers for a record.
func (*Client) PullStream ¶
func (c *Client) PullStream(ctx context.Context, refsCh <-chan *corev1.RecordRef) (streaming.StreamResult[corev1.Record], error)
PullStream retrieves multiple records efficiently using a single bidirectional stream. This method is ideal for batch operations and takes full advantage of gRPC streaming. The input channel allows you to send record refs as they become available.
func (*Client) Push ¶
Push sends a complete record to the store and returns a record reference. This is a convenience wrapper around PushBatch for single-record operations. The record must be ≤4MB as per the v1 store service specification.
func (*Client) PushBatch ¶
func (c *Client) PushBatch(ctx context.Context, records []*corev1.Record) ([]*corev1.RecordRef, error)
PushBatch sends multiple records in a single stream for efficiency. This is a convenience method that accepts a slice and returns a slice, built on top of the streaming implementation for consistency.
func (*Client) PushReferrer ¶
func (c *Client) PushReferrer(ctx context.Context, req *storev1.PushReferrerRequest) (*storev1.PushReferrerResponse, error)
PushReferrer stores a signature using the PushReferrer RPC.
func (*Client) PushStream ¶
func (c *Client) PushStream(ctx context.Context, recordsCh <-chan *corev1.Record) (streaming.StreamResult[corev1.RecordRef], error)
PushStream uploads multiple records efficiently using a single bidirectional stream. This method is ideal for batch operations and takes full advantage of gRPC streaming. The input channel allows you to send records as they become available.
func (*Client) Resolve ¶ added in v1.0.0
func (c *Client) Resolve(ctx context.Context, name string, version string) (*namingv1.ResolveResponse, error)
Resolve resolves a record reference (name with optional version) to CIDs. Returns all matching records sorted by created_at descending (newest first). If version is empty, returns all versions; otherwise returns matches for the specific version.
func (*Client) SearchCIDs ¶ added in v0.5.6
func (c *Client) SearchCIDs(ctx context.Context, req *searchv1.SearchCIDsRequest) (streaming.StreamResult[searchv1.SearchCIDsResponse], error)
SearchCIDs searches for record CIDs matching the given request.
func (*Client) SearchRecords ¶ added in v0.5.6
func (c *Client) SearchRecords(ctx context.Context, req *searchv1.SearchRecordsRequest) (streaming.StreamResult[searchv1.SearchRecordsResponse], error)
SearchRecords searches for full records matching the given request.
func (*Client) SearchRouting ¶
func (c *Client) SearchRouting(ctx context.Context, req *routingv1.SearchRequest) (<-chan *routingv1.SearchResponse, error)
func (*Client) Sign ¶
func (c *Client) Sign(ctx context.Context, req *signv1.SignRequest) (*signv1.SignResponse, error)
Sign routes to the appropriate signing method based on provider type. This is the main entry point for signing operations.
func (*Client) Verify ¶
func (c *Client) Verify(ctx context.Context, req *signv1.VerifyRequest) (*signv1.VerifyResponse, error)
Verify verifies signatures for a record. When from_server is true, the result is the server's cached verification; when false, verification is performed locally.
type Config ¶
type Config struct {
ServerAddress string `json:"server_address,omitempty" mapstructure:"server_address"`
TlsSkipVerify bool `json:"tls_skip_verify,omitempty" mapstructure:"tls_skip_verify"`
TlsCertFile string `json:"tls_cert_file,omitempty" mapstructure:"tls_cert_file"`
TlsKeyFile string `json:"tls_key_file,omitempty" mapstructure:"tls_key_file"`
TlsCAFile string `json:"tls_ca_file,omitempty" mapstructure:"tls_ca_file"`
SpiffeSocketPath string `json:"spiffe_socket_path,omitempty" mapstructure:"spiffe_socket_path"`
SpiffeToken string `json:"spiffe_token,omitempty" mapstructure:"spiffe_token"`
AuthMode string `json:"auth_mode,omitempty" mapstructure:"auth_mode"`
JWTAudience string `json:"jwt_audience,omitempty" mapstructure:"jwt_audience"`
// OAuth configuration (for browser-based login)
GitHubClientID string `json:"github_client_id,omitempty" mapstructure:"github_client_id"`
GitHubClientSecret string `json:"github_client_secret,omitempty" mapstructure:"github_client_secret"`
// GitHub token (PAT or OAuth) - can be set via flag/env for CI/CD use
// Developers: use 'dirctl auth login' instead
// CI/CD: set via DIRECTORY_CLIENT_GITHUB_TOKEN env var or --github-token flag
GitHubToken string `json:"github_token,omitempty" mapstructure:"github_token"`
}
func LoadConfig ¶
type DeviceCodeResponse ¶ added in v1.0.0
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"` // Minimum seconds between polls
}
DeviceCodeResponse is the response from GitHub's device code endpoint.
type DeviceFlowConfig ¶ added in v1.0.0
type DeviceFlowConfig struct {
ClientID string
Scopes []string
Output io.Writer // Where to write user instructions (default: os.Stdout)
}
DeviceFlowConfig configures the device authorization flow.
type DeviceFlowError ¶ added in v1.0.0
type DeviceFlowError struct {
Code string
Description string
NewInterval int // New polling interval (for slow_down errors)
}
DeviceFlowError represents an OAuth2 device flow error.
func (*DeviceFlowError) Error ¶ added in v1.0.0
func (e *DeviceFlowError) Error() string
Error implements the error interface.
type DeviceFlowResult ¶ added in v1.0.0
type DeviceFlowResult struct {
AccessToken string //nolint:gosec // G117: intentional field for OAuth token
TokenType string
Scope string
ExpiresAt time.Time // Calculated expiry (GitHub doesn't provide expires_in for device flow)
}
DeviceFlowResult contains the successful device flow result.
func StartDeviceFlow ¶ added in v1.0.0
func StartDeviceFlow(ctx context.Context, config *DeviceFlowConfig) (*DeviceFlowResult, error)
StartDeviceFlow initiates GitHub OAuth2 device authorization flow. This flow is ideal for CLI applications, SSH sessions, and headless environments.
The flow:
- Request device and user codes from GitHub
- Display verification URL and user code to the user
- Poll GitHub until user completes authorization
- Return access token
The user can complete authorization on any device (phone, laptop, etc.).
type DeviceTokenResponse ¶ added in v1.0.0
type DeviceTokenResponse struct {
AccessToken string `json:"access_token"` //nolint:gosec // G117: intentional field for OAuth token
TokenType string `json:"token_type"`
Scope string `json:"scope"`
Error string `json:"error,omitempty"`
ErrorDescription string `json:"error_description,omitempty"`
Interval int `json:"interval,omitempty"` // New interval when slow_down is returned
}
DeviceTokenResponse is the response from GitHub's token endpoint during polling.
type OAuthConfig ¶ added in v1.0.0
type OAuthConfig struct {
// ClientID is the GitHub OAuth App client ID.
ClientID string
// ClientSecret is the GitHub OAuth App client secret.
// This can be empty for public clients using PKCE.
ClientSecret string //nolint:gosec // G117: intentional field
// Scopes are the OAuth scopes to request.
// Default: ["user:email", "read:org"]
Scopes []string
// CallbackPort is the port for the local callback server.
// Default: 8484
CallbackPort int
// Timeout is the maximum time to wait for the OAuth flow.
// Default: 5 minutes
Timeout time.Duration
// SkipBrowserOpen skips automatically opening the browser.
// Useful for headless environments or testing.
SkipBrowserOpen bool
// Output is where to write status messages.
// Default: os.Stdout
Output io.Writer
}
OAuthConfig holds the configuration for GitHub OAuth.
type OAuthTokenResult ¶ added in v1.0.0
type OAuthTokenResult struct {
// AccessToken is the GitHub access token.
AccessToken string //nolint:gosec // G117: intentional field
// TokenType is the token type (usually "bearer").
TokenType string
// ExpiresAt is when the token expires (if available).
ExpiresAt time.Time
// Scopes are the granted scopes.
Scopes []string
}
OAuthTokenResult holds the result of a successful OAuth flow.
func InteractiveLogin ¶ added in v1.0.0
func InteractiveLogin(ctx context.Context, cfg OAuthConfig) (*OAuthTokenResult, error)
InteractiveLogin performs an interactive browser-based GitHub OAuth login. It opens the user's browser to GitHub's authorization page, starts a local HTTP server to receive the callback, and exchanges the code for an access token.
type Option ¶
type Option func(*options) error
func WithConfig ¶
func WithEnvConfig ¶
func WithEnvConfig() Option
type TokenCache ¶ added in v1.0.0
type TokenCache struct {
// CacheDir is the directory where tokens are stored.
CacheDir string
}
TokenCache manages cached authentication tokens from any provider.
func NewTokenCache ¶ added in v1.0.0
func NewTokenCache() *TokenCache
NewTokenCache creates a new token cache with the default directory. Respects XDG_CONFIG_HOME environment variable for config directory location.
func NewTokenCacheWithDir ¶ added in v1.0.0
func NewTokenCacheWithDir(dir string) *TokenCache
NewTokenCacheWithDir creates a new token cache with a custom directory.
func (*TokenCache) Clear ¶ added in v1.0.0
func (c *TokenCache) Clear() error
Clear removes the cached token.
func (*TokenCache) GetCachePath ¶ added in v1.0.0
func (c *TokenCache) GetCachePath() string
GetCachePath returns the full path to the token cache file.
func (*TokenCache) GetValidToken ¶ added in v1.0.0
func (c *TokenCache) GetValidToken() (*CachedToken, error)
GetValidToken returns a valid cached token or nil if none exists.
func (*TokenCache) IsValid ¶ added in v1.0.0
func (c *TokenCache) IsValid(token *CachedToken) bool
IsValid checks if a cached token is still valid. A token is considered valid if it exists and hasn't expired.
func (*TokenCache) Load ¶ added in v1.0.0
func (c *TokenCache) Load() (*CachedToken, error)
Load loads the cached token from disk. Returns nil if no valid token is found.
func (*TokenCache) Save ¶ added in v1.0.0
func (c *TokenCache) Save(token *CachedToken) error
Save saves a token to the cache.
type TokenCacheEntry ¶ added in v1.0.0
type TokenCacheEntry = CachedToken
TokenCacheEntry is an alias for CachedToken (for compatibility).