bugger/docs/HIGH_LEVEL_DESIGN.md

8.0 KiB

Bugger for macOS — High-Level Design

Overview

Bugger is a lightweight macOS menu bar application that surfaces bugs assigned to you from a Feishu Bitable. It mirrors the experience of the Windows Bugger tool: a glanceable badge in the menu bar, a popover with your active bugs, native notifications when bugs are assigned or changed, and an optional floating widget.

Architecture

┌──────────────────────────────────────────────────────┐
│                     User's Mac                        │
│                                                       │
│  ┌─────────────┐    ┌──────────────┐                  │
│  │  Menu Bar    │    │   Floating    │                  │
│  │  Icon+Badge  │    │   Widget      │                  │
│  │  [🐛 3]     │    │  (optional)   │                  │
│  └──────┬──────┘    └──────┬───────┘                  │
│         │                  │                           │
│  ┌──────┴──────────────────┴───────┐                  │
│  │         BugStore                 │                  │
│  │    (ObservableObject)           │                  │
│  │    - bugs: [Bug]                │                  │
│  │    - unseenCount: Int           │                  │
│  │    - lastUpdated: Date          │                  │
│  └──────┬──────────────────────────┘                  │
│         │                                              │
│  ┌──────┴──────────┐    ┌─────────────┐               │
│  │  PollerService   │───▶│ FeishuService│              │
│  │  (Timer, 5min)  │    │             │               │
│  └─────────────────┘    └──────┬──────┘               │
│                                │                       │
│  ┌──────────────┐    ┌────────┴───────┐               │
│  │ Notification  │    │  TokenManager   │              │
│  │ Service       │    │  (Keychain)     │              │
│  └──────────────┘    └────────────────┘               │
│                                                       │
└──────────────────────────────────────────────────────┘
                          │
                          │ HTTPS (OAuth Bearer)
                          ▼
┌──────────────────────────────────────────────────────┐
│                  Feishu Cloud                          │
│  ┌──────────────┐    ┌──────────────────┐             │
│  │  OAuth       │    │  Bitable API      │             │
│  │  /authen/v1/  │    │  /bitable/v1/     │             │
│  │  oidc/       │    │  apps/{token}/    │             │
│  │  access_token│    │  tables/{id}/     │             │
│  └──────────────┘    │  records          │             │
│                       └──────────────────┘             │
└──────────────────────────────────────────────────────┘

Key Design Decisions

1. Native SwiftUI (not cross-platform)

The app targets macOS exclusively. SwiftUI + AppKit bridging gives the best integration with macOS idioms — MenuBarExtra, NSPanel floating windows, Keychain, and UserNotifications — while keeping the binary under 10 MB.

2. Poll-based sync, not push

Feishu webhooks require a public-facing HTTP endpoint. For a personal tool, polling the Bitable API every N minutes is simpler, safer, and sufficient. Default interval: 5 minutes.

3. OAuth user_access_token with refresh

Uses Feishu's OAuth 2.0 authorization code flow to get a user_access_token (valid 2h) and refresh_token (valid 30 days). Tokens are stored in the macOS Keychain. The app acts on behalf of the user — no admin approval needed.

4. No backend server

Everything runs locally. No database, no server, no cloud hosting. The app stores only:

  • OAuth tokens (Keychain)
  • Configuration (UserDefaults: table ID, polling interval, etc.)
  • Cached bug state (in-memory, rebuilt on launch)

5. Menu bar first, floating widget second

The menu bar popover is the primary interaction surface. The floating widget is an optional companion — a small always-on-top window showing the count, which clicks through to open the menu bar popover.

Component Map

Component Responsibility
App @main entry, sets activation policy to .accessory (no dock icon)
AppDelegate Menu bar icon registration, window management
BugStore Central observable state: bug list, unseen count, loading/error
FeishuService HTTP client for Feishu Open API (bitable records, OAuth)
TokenManager OAuth flow orchestration, Keychain read/write, token refresh
PollerService Configurable timer driving the fetch cycle
NotificationService Diff engine + UNUserNotificationCenter push
MenuBarView Menu bar icon with badge count
BugListPopover Popover containing the scrollable bug list
BugRow Single bug: title, priority pill, age, clickable
FloatingWidget Optional NSPanel-based always-on-top overlay
SettingsWindow Preferences: table config, poll interval, widget toggle
KeychainHelper Thin wrapper around Security framework

Data Flow

1. App Launch
   ├── Load tokens from Keychain
   ├── If no token → show OAuth setup window
   ├── If token expired → refresh via refresh_token
   └── Start PollerService

2. Poll Cycle (every 5 min, configurable)
   ├── FeishuService.fetchRecords(table_id, filter=assignee=me)
   ├── Parse response → [Bug]
   ├── BugStore.diff(old, new)
   │   ├── New bugs → NotificationService.fire()
   │   ├── Status changes → NotificationService.fire()
   │   └── Assignee changes → NotificationService.fire()
   └── BugStore.bugs = new; BugStore.lastUpdated = now

3. User Interaction
   ├── Click menu bar icon → toggle popover
   ├── Click bug in popover → open in Feishu (browser / Feishu app URL)
   ├── "Mark all seen" → reset badge count
   └── Floating widget click → open menu bar popover

Feishu API Surface

API Method Purpose
/authen/v1/oidc/access_token POST Exchange authorization code for user_access_token
/authen/v1/refresh_access_token POST Refresh expired user_access_token
/bitable/v1/apps/{app_token}/tables/{table_id}/records GET Fetch bug records with filter

All calls use Authorization: Bearer <user_access_token> and go to https://open.feishu.cn.

Non-Functional Requirements

  • Memory: < 80 MB at steady state
  • CPU: idle < 0.1%, spike < 2% during poll
  • Binary: < 15 MB
  • Startup: < 2 seconds to menu bar icon visible
  • Offline: graceful degradation (show stale data, retry on next interval)
  • macOS: 14.0+ (Sonoma) — MenuBarExtra is stable from 13.3, but 14.0 is a reasonable floor for 2024+