import type { CookieBotSchedule } from "@/lib/cookie-bot"; import type { RemoteSessionState } from "@/lib/remote-sessions"; export interface ProxySettings { proxy_type: string; host: string; port: number; username?: string; password?: string; vless_uri?: string; } export interface TableSortingSettings { column: string; // "name", "note", "status" direction: string; // "asc" or "desc" } export interface BrowserProfile { id: string; // UUID of the profile name: string; browser: string; version: string; proxy_id?: string; // Reference to stored proxy vpn_id?: string; // Reference to stored VPN config launch_hook?: string; process_id?: number; last_launch?: number; release_type: string; wayfern_config?: WayfernConfig; // Wayfern configuration group_id?: string; // Reference to profile group tags?: string[]; note?: string; // User note window_color?: string; // Per-profile window frame color "#RRGGBB"; auto-derived from the id when unset sync_mode?: SyncMode; encryption_salt?: string; last_sync?: number; // Timestamp of last successful sync (epoch seconds) host_os?: string; // OS where profile was created ("macos", "windows", "linux") ephemeral?: boolean; clear_on_close?: boolean; extension_group_id?: string; proxy_bypass_rules?: string[]; created_by_id?: string; created_by_email?: string; /** Profile creation timestamp (epoch seconds, UTC). Undefined for legacy * profiles created before this field existed. */ created_at?: number; dns_blocklist?: string; password_protected?: boolean; } export interface Extension { id: string; name: string; file_name: string; file_type: string; browser_compatibility: string[]; created_at: number; updated_at: number; sync_enabled?: boolean; last_sync?: number; version?: string; description?: string; author?: string; homepage_url?: string; } export interface ExtensionGroup { id: string; name: string; extension_ids: string[]; created_at: number; updated_at: number; sync_enabled?: boolean; last_sync?: number; } export type SyncMode = "Disabled" | "Regular" | "Encrypted"; export type SyncStatus = "Disabled" | "Syncing" | "Synced" | "Error"; export interface SyncSettings { sync_server_url?: string; sync_token?: string; } /** * Capability/limit set derived from the plan by the backend. Features are gated * on these flags instead of a single "is paid?" check, so a plan like the future * "starter" tier (cross-OS fingerprints + cloud backup, no automation) is just * data. Mirrors `apps/backend/src/plans/entitlements.ts`. Resolve via * `getEntitlements()` — the desktop populates it, but it stays optional for * safety on older state. */ export interface Entitlements { active: boolean; browserAutomation: boolean; crossOsFingerprints: boolean; cloudBackup: boolean; teamCollaboration: boolean; /** Overnight profile warming on a leased remote host. */ cookieBot: boolean; profileLimit: number; requestsPerHour: number; /** * Per-seat monthly allowance for remote sessions. Reporting only: the * spendable figure is whatever `get_remote_hours_quota` returns, because a * team pools this across its seats and only the server knows the seat count. */ remoteBrowserHours: number; } /** * What a backend older than the cookie-bot release actually sends. Read it * through `getEntitlements()`, which fills the gap — never off `CloudUser` * directly, or a paying customer's Cookie Bot silently reads `false`. */ export type ServerEntitlements = Omit< Entitlements, "cookieBot" | "remoteBrowserHours" > & Partial>; export interface CloudUser { id: string; email: string; plan: string; planPeriod: string | null; subscriptionStatus: string; profileLimit: number; cloudProfilesUsed: number; proxyBandwidthLimitMb: number; proxyBandwidthUsedMb: number; proxyBandwidthExtraMb: number; teamId?: string; teamName?: string; teamRole?: string; // This device's position among the user's active devices (oldest = 1). // Ordinal 1 / isPrimaryDevice === true is the only device that can run // browser automation. Optional: older backends omit them. deviceOrdinal?: number | null; deviceCount?: number | null; isPrimaryDevice?: boolean | null; // Plan-derived capabilities. The desktop resolves this before handing CloudUser // to the UI; optional to stay safe on older cached state. entitlements?: ServerEntitlements; } /** * Cookie Bot and remote-session wire types. Defined next to the transport that * owns them (`src/lib/cookie-bot.ts`, `src/lib/remote-sessions.ts`) and * re-exported here so a component reads one module. Type-only, so nothing is * pulled into the bundle. */ export type { CookieBotConflict, CookieBotPreset, CookieBotPresetList, CookieBotRun, CookieBotRunPage, CookieBotRunStarted, CookieBotSchedule, CookieBotScheduleInput, CookieBotScheduleList, CookieBotScheduleSaved, CookieBotScope, CookieBotUsage, CookieBotUsageMember, CookieBotUsageProfile, RemoteHoursMember, RemoteHoursQuota, } from "@/lib/cookie-bot"; export type { RemoteSessionPhase, RemoteSessionSnapshot, RemoteSessionState, } from "@/lib/remote-sessions"; /** Where a profile stands with the bot, as one row of the profile table reads it. */ export interface ProfileBotState { /** The stored enrolment, or null when the profile is not enrolled. */ schedule: CookieBotSchedule | null; /** A remote session for this profile that has not closed yet. */ liveSession: RemoteSessionState | null; } export interface ProfileLockInfo { profileId: string; lockedBy: string; lockedByEmail: string; lockedAt: string; expiresAt?: string; } export interface CloudAuthState { user: CloudUser; logged_in_at: string; } export interface ProfileSyncStatusEvent { profile_id: string; status: "disabled" | "syncing" | "synced" | "error" | "pending"; } export interface ProxyCheckResult { ip: string; city?: string; country?: string; country_code?: string; timestamp: number; is_valid: boolean; } export function isSyncEnabled(profile: BrowserProfile): boolean { return profile.sync_mode != null && profile.sync_mode !== "Disabled"; } export const CLOUD_PROXY_ID = "cloud-included-proxy"; export interface StoredProxy { id: string; name: string; proxy_settings: ProxySettings; sync_enabled?: boolean; last_sync?: number; is_cloud_managed?: boolean; is_cloud_derived?: boolean; geo_country?: string; geo_state?: string; geo_region?: string; geo_city?: string; geo_isp?: string; } export interface LocationItem { code: string; name: string; } export interface ProfileGroup { id: string; name: string; sync_enabled?: boolean; last_sync?: number; } export interface GroupWithCount { id: string; name: string; count: number; sync_enabled?: boolean; last_sync?: number; } export interface DetectedProfile { browser: string; name: string; path: string; description: string; mapped_browser: string; } export interface ImportProfileItem { source_path: string; browser_type?: string; new_profile_name: string; /** Mutually exclusive with `vpn_id`; the importer rejects setting both. */ proxy_id?: string | null; vpn_id?: string | null; } export interface ProfileImportItemResult { name: string; source_path: string; status: "imported" | "skipped" | "failed"; profile_id: string | null; error: string | null; } export interface ProfileImportBatchResult { imported_count: number; skipped_count: number; failed_count: number; results: ProfileImportItemResult[]; } export interface ArchiveScanResult { extracted_dir: string; profiles: DetectedProfile[]; } export interface ProfileImportProgress { total: number; completed: number; index: number; name: string; status: "importing" | "imported" | "skipped" | "failed"; } export interface BrowserReleaseTypes { stable?: string; } export interface AppUpdateInfo { current_version: string; new_version: string; release_notes: string; download_url: string; is_nightly: boolean; published_at: string; manual_update_required: boolean; release_page_url?: string; repo_update: boolean; /** URL of the release's SHA256SUMS.txt; downloads are verified against it. */ checksums_url?: string | null; /** GitHub-computed digest of the chosen asset ("sha256:"). */ asset_digest?: string | null; } export interface AppUpdateProgress { stage: string; // "downloading", "extracting", "installing", "completed" percentage?: number; speed?: string; // MB/s eta?: string; // estimated time remaining message: string; } export type WayfernOS = "windows" | "macos" | "linux" | "android" | "ios"; export interface WayfernConfig { proxy?: string; screen_max_width?: number; screen_max_height?: number; screen_min_width?: number; screen_min_height?: number; geoip?: string | boolean; // For compatibility with shared config form block_images?: boolean; // For compatibility with shared config form block_webrtc?: boolean; block_webgl?: boolean; executable_path?: string; fingerprint?: string; // JSON string of the complete fingerprint config randomize_fingerprint_on_launch?: boolean; // Generate new fingerprint on every launch os?: WayfernOS; // Operating system for fingerprint generation geo_proxy_signature?: string; // Internal: routing the fingerprint's location was computed for } // Wayfern fingerprint config - matches the C++ FingerprintData structure export interface WayfernFingerprintConfig { // User agent and platform userAgent?: string; platform?: string; platformVersion?: string; brand?: string; brandVersion?: string; // Hardware hardwareConcurrency?: number; maxTouchPoints?: number; deviceMemory?: number; // Screen screenWidth?: number; screenHeight?: number; screenAvailWidth?: number; screenAvailHeight?: number; screenColorDepth?: number; screenPixelDepth?: number; devicePixelRatio?: number; // Window windowOuterWidth?: number; windowOuterHeight?: number; windowInnerWidth?: number; windowInnerHeight?: number; screenX?: number; screenY?: number; // Language language?: string; languages?: string[]; // Browser features doNotTrack?: string; cookieEnabled?: boolean; webdriver?: boolean; pdfViewerEnabled?: boolean; // WebGL webglVendor?: string; webglRenderer?: string; webglVersion?: string; webglShadingLanguageVersion?: string; webglParameters?: string; // JSON string webgl2Parameters?: string; // JSON string webglShaderPrecisionFormats?: string; // JSON string webgl2ShaderPrecisionFormats?: string; // JSON string // Timezone and geolocation timezone?: string; timezoneOffset?: number; latitude?: number; longitude?: number; accuracy?: number; // Media queries / preferences prefersReducedMotion?: boolean; prefersDarkMode?: boolean; prefersContrast?: string; prefersReducedData?: boolean; // Color/HDR colorGamutSrgb?: boolean; colorGamutP3?: boolean; colorGamutRec2020?: boolean; hdrSupport?: boolean; // Audio audioSampleRate?: number; audioMaxChannelCount?: number; // Storage localStorage?: boolean; sessionStorage?: boolean; indexedDb?: boolean; // Canvas canvasNoiseSeed?: string; // Fonts, plugins, mime types (JSON strings) fonts?: string; // JSON array string plugins?: string; // JSON array string mimeTypes?: string; // JSON array string // Battery (optional) batteryCharging?: boolean; batteryChargingTime?: number; batteryDischargingTime?: number; batteryLevel?: number; // Voices voices?: string; // JSON array string // Vendor info vendor?: string; vendorSub?: string; productSub?: string; // Network (optional) connectionEffectiveType?: string; connectionDownlink?: number; connectionRtt?: number; // Performance performanceMemory?: number; } export interface WayfernLaunchResult { id: string; processId?: number; profilePath?: string; url?: string; cdp_port?: number; } // Synchronizer types export interface SyncFollowerState { profile_id: string; profile_name: string; failed_at_url: string | null; } export interface SyncSessionInfo { id: string; leader_profile_id: string; leader_profile_name: string; followers: SyncFollowerState[]; } // Traffic stats types export interface BandwidthDataPoint { timestamp: number; bytes_sent: number; bytes_received: number; } export interface DomainAccess { domain: string; request_count: number; bytes_sent: number; bytes_received: number; first_access: number; last_access: number; } export interface TrafficStats { proxy_id: string; profile_id?: string; session_start: number; last_update: number; total_bytes_sent: number; total_bytes_received: number; total_requests: number; bandwidth_history: BandwidthDataPoint[]; domains: Record; unique_ips: string[]; } export interface TrafficSnapshot { profile_id?: string; session_start: number; last_update: number; total_bytes_sent: number; total_bytes_received: number; total_requests: number; current_bytes_sent: number; current_bytes_received: number; recent_bandwidth: BandwidthDataPoint[]; } export interface FilteredTrafficStats { profile_id?: string; session_start: number; last_update: number; total_bytes_sent: number; total_bytes_received: number; total_requests: number; bandwidth_history: BandwidthDataPoint[]; period_bytes_sent: number; period_bytes_received: number; period_requests: number; domains: Record; unique_ips: string[]; } // Cookie copy types export interface UnifiedCookie { name: string; value: string; domain: string; path: string; expires: number; is_secure: boolean; is_http_only: boolean; same_site: number; creation_time: number; last_accessed: number; } export interface DomainCookies { domain: string; cookies: UnifiedCookie[]; cookie_count: number; } export interface CookieReadResult { profile_id: string; browser_type: string; domains: DomainCookies[]; total_count: number; } export interface SelectedCookie { domain: string; name: string; } export interface CookieCopyRequest { source_profile_id: string; target_profile_ids: string[]; selected_cookies: SelectedCookie[]; } export interface CookieCopyResult { target_profile_id: string; cookies_copied: number; cookies_replaced: number; errors: string[]; } // Proxy import/export types export interface ProxyExportData { version: string; proxies: ExportedProxy[]; exported_at: string; source: string; } export interface ExportedProxy { name: string; type: string; host: string; port: number; username?: string; password?: string; } export interface ProxyImportResult { imported_count: number; skipped_count: number; errors: string[]; proxies: StoredProxy[]; } export interface ParsedProxyLine { proxy_type: string; host: string; port: number; username?: string; password?: string; vless_uri?: string; original_line: string; } export type ProxyParseResult = | ({ status: "parsed" } & ParsedProxyLine) | { status: "ambiguous"; line: string; possible_formats: string[] } | { status: "invalid"; line: string; reason: string }; // VPN types export type VpnType = "WireGuard"; export interface VpnConfig { id: string; name: string; vpn_type: VpnType; config_data: string; // Raw config content (may be empty in list view) created_at: number; last_used?: number; sync_enabled?: boolean; last_sync?: number; } export interface VpnImportResult { success: boolean; vpn_id?: string; vpn_type?: VpnType; name: string; error?: string; } export interface VpnStatus { connected: boolean; vpn_id: string; connected_at?: number; bytes_sent?: number; bytes_received?: number; last_handshake?: number; }