usage

package
v0.0.34 Latest Latest
Warning

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

Go to latest
Published: Mar 20, 2026 License: AGPL-3.0 Imports: 36 Imported by: 0

Documentation

Overview

Critical no-block safeguards for transaction-like pages.

Why this exists: Blocking the wrong page can break real-world user actions with consequences, such as failed payments, lost checkout sessions, duplicate charges, expired 3DS challenges, or interrupted booking/reservation confirmations. Those are high-cost interruptions, so we bias toward safety and avoid classifying such flows as distracting.

How it works:

  1. Deterministic URL/provider signals catch high-confidence payment and booking flows (e.g. known gateway hosts and checkout/billing/confirmation paths) and force neutral.
  2. Suspicious context detection marks ambiguous cases so callers can apply a fail-safe neutral outcome when LLM classification is uncertain (error/low confidence).

This keeps strict protection where it matters while reducing false positives from weak keyword-only title/content matches.

Index

Constants

View Source
const (
	TerminationModeNone  TerminationMode = "none"
	TerminationModeBlock TerminationMode = "block"
	TerminationModeAllow TerminationMode = "allow"

	TerminationModeSourceApplication TerminationModeSource = "application"
	TerminationModeSourceCustomRules TerminationModeSource = "custom_rules"
	TerminationModeSourceWhitelist   TerminationModeSource = "whitelist"
	TerminationModeSourcePaused      TerminationModeSource = "paused"

	ClassificationSourceUserSet           ClassificationSource = "user_set"
	ClassificationSourceObviously         ClassificationSource = "obviously"
	ClassificationSourceCustomRules       ClassificationSource = "custom_rules"
	ClassificationSourceCloudLLMGemini    ClassificationSource = "llm_gemini"
	ClassificationSourceCloudLLMOpenAI    ClassificationSource = "llm_openai"
	ClassificationSourceCloudLLMGroq      ClassificationSource = "llm_grok"
	ClassificationSourceCloudLLMAnthropic ClassificationSource = "llm_anthropic"

	IdleApplicationName = "Idle"

	ClassificationNone        Classification = "none"
	ClassificationProductive  Classification = "productive"
	ClassificationDistracting Classification = "distracting"
	ClassificationNeutral     Classification = "neutral"
	ClassificationSystem      Classification = "system"
)

Variables

This section is empty.

Functions

func FetchMainContent

func FetchMainContent(ctx context.Context, rawURL string) (string, error)

func NewSandboxContext added in v0.0.34

func NewSandboxContext(opts ...sandboxContextOption) sandboxContext

func WithAppNameContext added in v0.0.34

func WithAppNameContext(appName string) sandboxContextOption

func WithBrowserURLContext added in v0.0.34

func WithBrowserURLContext(url string) sandboxContextOption

func WithMinutesSinceLastBlockContext added in v0.0.34

func WithMinutesSinceLastBlockContext(minutesSinceLastBlock int) sandboxContextOption

func WithMinutesUsedInPeriodContext added in v0.0.34

func WithMinutesUsedInPeriodContext(minutesUsedInPeriod func(bundleID, hostname string, durationMinutes int64) (int64, error)) sandboxContextOption

func WithMinutesUsedSinceLastBlockContext added in v0.0.34

func WithMinutesUsedSinceLastBlockContext(minutesUsedSinceLastBlock int) sandboxContextOption

func WithNowContext added in v0.0.34

func WithNowContext(now time.Time) sandboxContextOption

func WithWindowTitleContext added in v0.0.34

func WithWindowTitleContext(title string) sandboxContextOption

Types

type AppClassifier added in v0.0.34

type AppClassifier func(ctx context.Context, appName, title string, bundleID, appCategory *string) (*ClassificationResponse, error)

type Application

type Application struct {
	// mandatory fields
	ID   int64  `json:"id" gorm:"primaryKey;autoIncrement;not null"`
	Name string `json:"name" gorm:"uniqueIndex:idx_name_hostname_id;not null"`

	// optional fields
	Icon           *string `json:"icon"` // either app icon or favicon if host is present
	Hostname       *string `json:"hostname" gorm:"uniqueIndex:idx_name_hostname_id"`
	Domain         *string `json:"domain"`
	ExecutablePath string  `json:"executable_path"`

	// darwin only
	BundleID    *string `json:"bundle_id"`
	AppCategory *string `json:"app_category"` // LSApplicationCategoryType, e.g. "public.app-category.developer-tools"
}

Application represents a unique application that has been used by the user Application is unique by name and hostname that is

  • if the application is not a browser it is unique by name
  • if the application is a browser it is unique by name and domain eg. Chrome + google.com != Chrome + youtube.com, each of them will have its own application

func NewIdleApplication added in v0.0.34

func NewIdleApplication() Application

func (Application) NewUsage added in v0.0.34

func (a Application) NewUsage(windowTitle string, browserURL *string) ApplicationUsage

func (Application) TableName added in v0.0.25

func (a Application) TableName() string

type ApplicationTagsSlice added in v0.0.25

type ApplicationTagsSlice []ApplicationUsageTags

func (ApplicationTagsSlice) Tags added in v0.0.25

func (a ApplicationTagsSlice) Tags() []string

type ApplicationUsage

type ApplicationUsage struct {
	// mandatory fields
	ID              int64           `json:"id" gorm:"primaryKey;autoIncrement;not null"`
	WindowTitle     string          `json:"window_title" gorm:"not null"`
	StartedAt       int64           `json:"started_at" gorm:"not null"`
	Classification  Classification  `json:"classification" gorm:"index:idx_classification"`
	TerminationMode TerminationMode `json:"termination_mode" gorm:"not null"`

	// optional fields
	BrowserURL      *string `json:"browser_url" gorm:"type:text"`
	EndedAt         *int64  `json:"ended_at"`
	DurationSeconds *int    `json:"duration_seconds"`

	ClassificationError      *string               `gorm:"index:idx_classification_error" json:"classification_error"`
	ClassificationConfidence *float32              `json:"classification_confidence"`
	ClassificationReasoning  *string               `json:"classification_reasoning"`
	ClassificationSource     *ClassificationSource `json:"classification_source"`

	DetectedProject              *string `gorm:"index:idx_detected_project" json:"detected_project"`
	DetectedCommunicationChannel *string `gorm:"index:idx_detected_communication_channel" json:"detected_communication_channel"`

	TerminationReasoning *string                `json:"termination_reasoning"`
	TerminationSource    *TerminationModeSource `json:"termination_mode_source"`
	TerminationError     *string                `gorm:"index:idx_termination_mode_error" json:"termination_mode_error"`

	SandboxContext  *string `json:"sandbox_context" gorm:"type:text;nullable"`
	SandboxResponse *string `json:"sandbox_response" gorm:"type:text;nullable"`
	SandboxLogs     *string `json:"sandbox_logs" gorm:"type:text;nullable"`

	// relations
	Tags          []ApplicationUsageTags `gorm:"foreignKey:UsageID" json:"tags"`
	ApplicationID int64                  `json:"application_id"`
	Application   Application            `gorm:"foreignKey:ApplicationID" json:"application"`
}

func (*ApplicationUsage) CommunicationChannel added in v0.0.33

func (a *ApplicationUsage) CommunicationChannel() string

func (*ApplicationUsage) GetDetectedProject added in v0.0.33

func (a *ApplicationUsage) GetDetectedProject() string

func (*ApplicationUsage) HasDetectedProject added in v0.0.33

func (a *ApplicationUsage) HasDetectedProject() bool

func (*ApplicationUsage) IsCommunicationUsage added in v0.0.33

func (a *ApplicationUsage) IsCommunicationUsage() bool

func (ApplicationUsage) Same

Same returns true if the application usage is the same as the given application usage

func (*ApplicationUsage) String added in v0.0.34

func (a *ApplicationUsage) String() string

func (*ApplicationUsage) TableName

func (a *ApplicationUsage) TableName() string

type ApplicationUsageTags

type ApplicationUsageTags struct {
	ID      int64  `gorm:"primaryKey;autoIncrement" json:"id"`
	Tag     string `json:"tag"`
	UsageID int64  `json:"usage_id" gorm:"index:idx_usage_id"`
}

func (*ApplicationUsageTags) TableName added in v0.0.34

func (a *ApplicationUsageTags) TableName() string

type Classification

type Classification string

func (Classification) IsProductiveOrDistracting added in v0.0.33

func (c Classification) IsProductiveOrDistracting() bool

type ClassificationResponse

type ClassificationResponse struct {
	Classification       Classification       `json:"classification"`
	ClassificationSource ClassificationSource `json:"classification_source"`
	Reasoning            string               `json:"reasoning"`
	ConfidenceScore      float32              `json:"confidence_score"`
	// DetectedProject is inferred by the LLM from the window title or channel name.
	// For coding apps (VS Code, Xcode, etc.), it extracts the workspace/project name from the title format.
	// For communication apps (Slack), it extracts the project/team context if strongly implied by the channel name.
	DetectedProject string `json:"detected_project"`

	// DetectedCommunicationChannel is inferred by the LLM from the window title for communication apps.
	// E.g., for Slack it extracts "engineering" from "Slack | #engineering | Acme Corp".
	// This is only populated when the "communication" tag is assigned.
	DetectedCommunicationChannel string `json:"detected_communication_channel"`

	Tags []string `json:"tags"`

	SandboxContext  string  `json:"sandbox_context"`
	SandboxResponse *string `json:"sandbox_response"`
	SandboxLogs     string  `json:"sandbox_logs"`
}

type ClassificationSource

type ClassificationSource string

type ClassifyRequest

type ClassifyRequest struct {
	AppName        string         `json:"app_name"`
	ExecutablePath string         `json:"executable_path"`
	Hostname       string         `json:"hostname"`
	URL            string         `json:"url"`
	Classification Classification `json:"classification"`
}

type CommunicationBreakdown added in v0.0.31

type CommunicationBreakdown struct {
	Name            string `json:"name"`
	Channel         string `json:"channel"`
	DurationSeconds int    `json:"duration_seconds"`
}

type DayInsights

type DayInsights struct {
	ProductivityScore            ProductivityScore                 `json:"productivity_score"`
	ProductivityPerHourBreakdown ProductivityPerHourBreakdown      `json:"productivity_per_hour_breakdown"`
	LLMDailySummary              *LLMDailySummary                  `json:"llm_daily_summary"`
	TopDistractions              map[string]int                    `json:"top_distractions"`
	TopBlocked                   map[string]int                    `json:"top_blocked"`
	ProjectBreakdown             map[string]int                    `json:"project_breakdown"`
	CommunicationBreakdown       map[string]CommunicationBreakdown `json:"communication_breakdown"`
}

type ExecutionLogType added in v0.0.21

type ExecutionLogType string
const (
	ExecutionLogTypeClassification  ExecutionLogType = "classification"
	ExecutionLogTypeTerminationMode ExecutionLogType = "termination_mode"
)

type GetUsageListOptions

type GetUsageListOptions struct {
	Date            *time.Time
	Page            *int
	PageSize        *int
	StartedAt       *time.Time
	EndedAt         *time.Time
	TerminationMode *TerminationMode
	Classification  *Classification
	ApplicationID   *int64
	ApplicationName *string
	Hostname        *string
	BundleID        *string
}

type LLMAppTimeSummary added in v0.0.31

type LLMAppTimeSummary struct {
	App     string `json:"app"`
	Minutes int    `json:"minutes"`
	Visits  int    `json:"visits"`
}

type LLMDailySummary added in v0.0.31

type LLMDailySummary struct {
	ID         int64  `json:"id" gorm:"primaryKey;autoIncrement"`
	Date       string `json:"date" gorm:"uniqueIndex;not null"`
	Headline   string `json:"headline"`
	Narrative  string `json:"narrative"`
	KeyPattern string `json:"key_pattern"`
	Wins       string `json:"wins"` // JSON array of strings
	Suggestion string `json:"suggestion"`
	DayVibe    string `json:"day_vibe"`

	ContextSwitchCount  int `json:"context_switch_count"`
	LongestFocusMinutes int `json:"longest_focus_minutes"`
	DeepWorkMinutes     int `json:"deep_work_minutes"`
	BlockedAttemptCount int `json:"blocked_attempt_count"`

	CreatedAt int64 `json:"created_at"`
}

LLMDailySummary is the persisted daily summary generated by the LLM.

func (LLMDailySummary) TableName added in v0.0.31

func (LLMDailySummary) TableName() string

type LLMDaySummaryInput added in v0.0.31

type LLMDaySummaryInput struct {
	Date                    string                  `json:"date"`
	TotalProductiveMinutes  int                     `json:"total_productive_minutes"`
	TotalDistractiveMinutes int                     `json:"total_distractive_minutes"`
	FocusScore              int                     `json:"focus_score"`
	ContextSwitchCount      int                     `json:"context_switch_count"`
	LongestFocusStretchMin  int                     `json:"longest_focus_stretch_min"`
	DeepWorkSessions        []LLMDeepWorkSession    `json:"deep_work_sessions"`
	DeepWorkTotalMinutes    int                     `json:"deep_work_total_minutes"`
	DistractionCascades     []LLMDistractionCascade `json:"distraction_cascades"`
	TopDistractions         []LLMAppTimeSummary     `json:"top_distractions"`
	TopProductiveApps       []LLMAppTimeSummary     `json:"top_productive_apps"`
	MostProductiveHours     string                  `json:"most_productive_hours"`
	MostDistractiveHours    string                  `json:"most_distractive_hours"`
	BlockedAttemptCount     int                     `json:"blocked_attempt_count"`
	ProtectionPauseCount    int                     `json:"protection_pause_count"`
	AvgFocusScoreLast7Days  int                     `json:"avg_focus_score_last_7_days"`
	FocusScoreTrend         string                  `json:"focus_score_trend"`
}

LLMDaySummaryInput is the pre-computed data that gets serialized and sent to the LLM. It is never stored -- only used as an intermediate representation.

type LLMDeepWorkSession added in v0.0.31

type LLMDeepWorkSession struct {
	Start   string `json:"start"`
	End     string `json:"end"`
	App     string `json:"app"`
	Minutes int    `json:"minutes"`
}

type LLMDistractionCascade added in v0.0.31

type LLMDistractionCascade struct {
	TriggerTime    string   `json:"trigger_time"`
	TriggerApp     string   `json:"trigger_app"`
	CascadeApps    []string `json:"cascade_apps"`
	TotalMinutes   int      `json:"total_minutes"`
	ReturnedToWork string   `json:"returned_to_work_at"`
}

type MetaData

type MetaData struct {
	Property string
	Content  string
}

type Option

type Option func(*Service)

Option is a function that configures a Service.

type PauseRequets

type PauseRequets struct {
	DurationSeconds int    `json:"duration_seconds"`
	Reason          string `json:"reason"`
}

type ProductivityPerHourBreakdown

type ProductivityPerHourBreakdown map[int]ProductivityScore

type ProductivityScore

type ProductivityScore struct {
	ProductiveSeconds  int `json:"productive_seconds"`
	DistractiveSeconds int `json:"distractive_seconds"`
	IdleSeconds        int `json:"idle_seconds"`
	OtherSeconds       int `json:"other_seconds"`
	ProductivityScore  int `json:"productivity_score"`
}

type ProjectBreakdown added in v0.0.31

type ProjectBreakdown struct {
	Name            string `json:"name"`
	DurationSeconds int    `json:"duration_seconds"`
}

type ProtectionPause

type ProtectionPause struct {
	ID                       int64  `gorm:"primaryKey;autoIncrement" json:"id"`
	RequestedDurationSeconds int    `json:"requested_duration_seconds"`
	ActualDurationSeconds    int    `json:"actual_duration_seconds"`
	ResumedAt                int64  `json:"resumed_at"`
	ResumedReason            string `json:"resumed_reason"`
	CreatedAt                int64  `json:"created_at"`
	Reason                   string `json:"reason"`
}

func (*ProtectionPause) TableName

func (p *ProtectionPause) TableName() string

type ProtectionWhitelist

type ProtectionWhitelist struct {
	ID int64 `gorm:"primaryKey;autoIncrement" json:"id"`
	// ExpiresAt should be pre-calculated and set to the time when the whitelist expires
	ExpiresAt int64 `json:"expires_at"`

	AppName  string  `gorm:"uniqueIndex:idx_allow_usage_identity" json:"appname"`
	Hostname *string `gorm:"uniqueIndex:idx_allow_usage_identity" json:"hostname"`
}

func (*ProtectionWhitelist) TableName

func (p *ProtectionWhitelist) TableName() string

type SandboxExecutionLog

type SandboxExecutionLog struct {
	ID         int64   `gorm:"primaryKey;autoIncrement" json:"id"`
	Context    string  `json:"context" gorm:"type:text;nullable"`
	Response   *string `json:"response" gorm:"type:text;nullable"`
	Logs       string  `json:"logs" gorm:"type:text;nullable"`
	CreatedAt  int64   `json:"created_at" gorm:"index:idx_created_at"`
	FinishedAt *int64  `json:"finished_at" gorm:"index:idx_finished_at;nullable"`
	Error      *string `json:"error" gorm:"type:text;nullable"`
	Type       string  `json:"type" gorm:"index:idx_type"`
}

func (*SandboxExecutionLog) TableName added in v0.0.34

func (s *SandboxExecutionLog) TableName() string

type Service

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

func NewService

func NewService(ctx context.Context, db *gorm.DB, options ...Option) (*Service, error)

func (*Service) CalculateTerminationMode

func (s *Service) CalculateTerminationMode(ctx context.Context, appUsage *ApplicationUsage) (TerminationDecision, error)

CalculateTerminationMode determines whether an application or website should be blocked, allowed, or paused based on classification, custom rules, protection status, and whitelist entries.

This function evaluates multiple factors in order of priority: 1. Custom rules (if configured) - highest priority 2. Classification - non-distracting usage is always allowed 3. Protection pause status - if protection is paused, usage is allowed 4. Whitelist entries - temporarily whitelisted bundle ID/hostname combinations are allowed 5. Default blocking - distracting usage is blocked when protection is active

Parameters:

  • bundleID: The application bundle identifier (e.g., "com.example.app")
  • hostname: The website hostname (e.g., "example.com") - empty string for non-browser apps
  • domain: The domain name extracted from the URL
  • url: The full URL being accessed
  • classification: The classification result indicating whether the usage is distracting
  • terminationMode: The requested termination mode (may be overridden by custom rules)

Returns:

  • TerminationDecision: A decision containing the mode (Allow/Block/Paused), reasoning, and source
  • error: Database error if protection status or whitelist lookup fails

func (*Service) ClassifyCustomRules

func (s *Service) ClassifyCustomRules(ctx context.Context, opts ...sandboxContextOption) (*ClassificationResponse, error)

func (*Service) ClassifyWithLLM

func (s *Service) ClassifyWithLLM(ctx context.Context, appName, title string, url, bundleID, appCategory *string) (*ClassificationResponse, error)

func (*Service) GenerateLLMDailySummaryIfNeeded added in v0.0.31

func (s *Service) GenerateLLMDailySummaryIfNeeded(ctx context.Context) error

func (*Service) GetApplicationList added in v0.0.34

func (s *Service) GetApplicationList() ([]Application, error)

func (*Service) GetDayInsights

func (s *Service) GetDayInsights(date time.Time) (DayInsights, error)

func (*Service) GetPauseHistory

func (s *Service) GetPauseHistory(days int) ([]ProtectionPause, error)

GetPauseHistory retrieves the history of protection pauses within the specified number of days.

Parameters:

  • days: The number of days to look back (e.g., 7 for one week)

Returns:

  • []ProtectionPause: A slice of pause records ordered by creation time (newest first)
  • error: Database error if the query fails

func (*Service) GetProtectionStatus

func (s *Service) GetProtectionStatus() (ProtectionPause, error)

GetProtectionStatus retrieves the current protection pause status.

It queries for an active ProtectionPause record where ResumedAt is greater than the current time (indicating the pause is still active and hasn't been resumed yet). When a pause is created, ResumedAt is set to a future timestamp representing when the pause should automatically expire. When manually resumed, ResumedAt is updated to the current time, making it no longer match this query.

Returns:

  • ProtectionPause: The active pause record if protection is currently paused, or an empty ProtectionPause (ID == 0) if protection is active (not paused)
  • error: Database error if the query fails

func (*Service) GetSandboxExecutionLogs added in v0.0.21

func (s *Service) GetSandboxExecutionLogs(logType string, search string, page, pageSize int) ([]SandboxExecutionLog, error)

GetSandboxExecutionLogs retrieves paginated sandbox execution logs from the database. It supports fuzzy search on context and response fields, and filtering by log type. Only returns logs from the last 7 days.

func (*Service) GetUsageAggregation added in v0.0.24

func (s *Service) GetUsageAggregation(options GetUsageListOptions) ([]UsageAggregation, error)

func (*Service) GetUsageList

func (s *Service) GetUsageList(options GetUsageListOptions) ([]ApplicationUsage, error)

GetUsageList returns a list of application usages for the given date and pagination options

Parameters:

  • options: GetUsageListOptions
  • Date: The date to get usages for - useful for detailed analysis of a specific day usage
  • Page: The page number to get
  • PageSize: The number of usages per page

Returns:

  • []ApplicationUsage: The list of application usages

func (*Service) GetWhitelist

func (s *Service) GetWhitelist() ([]ProtectionWhitelist, error)

GetWhitelist returns all active whitelist entries that haven't expired.

Returns:

  • []ProtectionWhitelist: A slice of active whitelist entries
  • error: Database error if the query fails

func (*Service) IdleChanged

func (s *Service) IdleChanged(ctx context.Context, isIdle bool) (*ApplicationUsage, error)

IdleChanged is called when the idle state of the user changes (e.g. user starts or stops using the computer) When idle changes one of the following can happen:

  • if user has been idle and idle triggers again, keep the current idle usage open to ensure idempotency
  • if user has not been idle and idle triggers, close the current application usage and open a new idle usage
  • if user has been idle and idle stops, no direct usage change is performed here; the next TitleChanged event closes idle

func (*Service) OnLLMDailySummaryReady added in v0.0.34

func (s *Service) OnLLMDailySummaryReady(fn func(summary LLMDailySummary))

OnLLMDailySummaryReady subscribes a callback to the daily summary ready event.

func (*Service) OnProtectionPause added in v0.0.34

func (s *Service) OnProtectionPause(fn func(pause ProtectionPause))

OnProtectionPause subscribes a callback to the protection paused event.

func (*Service) OnProtectionResumed added in v0.0.34

func (s *Service) OnProtectionResumed(fn func(pause ProtectionPause))

OnProtectionResumed subscribes a callback to the protection resumed event.

func (*Service) OnUsageUpdated added in v0.0.34

func (s *Service) OnUsageUpdated(fn func(usage *ApplicationUsage))

OnUsageUpdated subscribes a callback to the usage updated event.

func (*Service) PauseProtection

func (s *Service) PauseProtection(durationSeconds int, reason string) (ProtectionPause, error)

PauseProtection temporarily disables focus protection for the specified duration.

The function starts a background goroutine that automatically resumes protection after the duration expires. The pause state is persisted to the database, allowing the application to recover pause state across restarts.

Parameters:

  • duration: The duration to pause protection (must be > 0)

Returns:

  • error: Returns an error if protection is already paused

Side effects:

  • Creates a ProtectionPause record in the database
  • Emits a state update via the state channel
  • Spawns a goroutine that calls ResumeProtection after the duration

func (*Service) RegisterHTTPHandlers

func (s *Service) RegisterHTTPHandlers(r *chi.Mux)

func (*Service) RemoveWhitelist

func (s *Service) RemoveWhitelist(id int64) error

RemoveWhitelist removes a whitelist entry by ID.

Parameters:

  • id: The ID of the whitelist entry to remove

Returns:

  • error: Database error if the deletion fails

func (*Service) ResumeProtection

func (s *Service) ResumeProtection(reason string) (ProtectionPause, error)

ResumeProtection re-enables focus protection and records the reason for resumption.

This function is called either automatically when a pause duration expires, or manually by the user to end a pause early. The reason is persisted to the database for auditing and analytics purposes.

Parameters:

  • reason: A human-readable explanation for why protection was resumed (e.g., "protection paused for 5m0s expired" or "user manually resumed")

Returns:

  • error: Returns an error if protection is not currently paused

Side effects:

  • Updates the ProtectionPause record in the database with ResumedAt timestamp
  • Clears the pause state and emits a state update via the state channel

func (*Service) TitleChanged

func (s *Service) TitleChanged(ctx context.Context, executablePath, windowTitle, appName, icon string, bundleID, browserURL, appCategory *string) (*ApplicationUsage, error)

TitleChanged is called when the title of the current application changes, whether it's a new application or the same application title has changed

func (*Service) Whitelist

func (s *Service) Whitelist(appname string, url string, duration time.Duration) error

Whitelist temporarily allows a specific blocked usage (by bundle ID and hostname) for the specified duration.

This function creates a ProtectionWhitelist entry that allows the specified application or website to bypass focus protection for a limited time. This enables users to temporarily access blocked content without pausing all protection. The whitelist entry is persisted to the database and can be checked during termination decision evaluation.

Parameters:

  • bundleID: The application bundle identifier (e.g., "com.example.app")
  • hostname: The website hostname (e.g., "example.com") - empty string for non-browser apps
  • duration: The duration to allow the usage (defaults to 1 hour if 0)

Returns:

  • error: Database error if the whitelist entry creation fails

Side effects:

  • Creates a ProtectionWhitelist record in the database with expiration timestamp

type TerminationDecision

type TerminationDecision struct {
	Mode      TerminationMode
	Reasoning string
	Source    TerminationModeSource
}

type TerminationMode

type TerminationMode string

type TerminationModeSource

type TerminationModeSource string

type UnpauseRequest

type UnpauseRequest struct {
	Reason string `json:"reason"`
}

type UnwhitelistRequest added in v0.0.24

type UnwhitelistRequest struct {
	ID int64 `json:"id"`
}

type UsageAggregation added in v0.0.24

type UsageAggregation struct {
	Application   Application `json:"application"`
	TotalDuration int         `json:"total_duration"` // in seconds
	UsageCount    int         `json:"usage_count"`
}

type WhitelistRequest added in v0.0.24

type WhitelistRequest struct {
	AppName         string `json:"app_name"`
	Hostname        string `json:"hostname"`
	DurationSeconds int    `json:"duration_seconds"`
}

Jump to

Keyboard shortcuts

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