Architecture split: extract PrivStack.Services and PrivStack.Server
Details
Phase 0 of the headless server architecture split. Extracts ~155 service
files with zero Avalonia dependency into a shared PrivStack.Services
library and creates a standalone PrivStack.Server headless binary.
Architecture changes:
- New PrivStack.Services project: shared core services, models, native
FFI, AI services, API server, biometric, connections, file sync, IPC,
plugin host, update services — all Avalonia-free
- New PrivStack.Server project: headless console binary (privstack-server)
that references Services + Sdk without any Avalonia dependency
- Desktop now references Services and only contains UI-specific code:
views, view models, theme/font/layout services, dialog service,
backup service, whisper/audio, spell check, plugin registry
Key abstractions created:
- INavigationHost: abstracts MainWindowViewModel navigation for Services
- IEmbeddingService: abstracts ONNX embedding (Desktop implements,
Server stubs)
- IWindowSettingsService: Desktop-only Window position/size persistence
- DesktopAppSettingsService: extends base AppSettingsService with
Avalonia Window operations
- Extensible AI provider registration via constructor injection
Breaking changes to models (Avalonia-free):
- SyncModels: DiscoveryBrush (IBrush) → DiscoveryCategory (string)
- CloudSyncModels: SeverityBrush (IBrush) → SeverityLevel (string)
- IAppSettingsService: removed ApplyToWindow/UpdateWindowBounds
- IDialogService: removed SetOwner/Owner
- IPluginRegistry: SetMainViewModel/GetMainViewModel use object?
Dependency graph:
Sdk (no deps)
↑
Services → Sdk
↑ ↑
Desktop → Services + Sdk + UI.Adaptive + Avalonia
Server → Services + Sdk (no Avalonia)
Add right-click context menus to Calendar events and sidebar calendars (BUG #65)
Details
Event context menu (all views: month, week, day, all-day, agenda):
- Edit Event — opens event editor
- Delete Event — triggers delete with recurring event handling
Sidebar calendar source context menu:
- Hide/Show Calendar — toggles calendar visibility
- Manage Calendars... — opens calendar manager overlay
Right-click is intercepted before drag handlers in week/day/month views
so it doesn't conflict with event drag-to-reposition.
Version: 1.14.4 → 1.14.5
Add headless API mode (--headless flag)
Details
PrivStack can now run as a headless API server without the Avalonia GUI,
enabling programmatic access via scripts, CI/CD, or background services.
CLI interface:
privstack --headless [--workspace <name>] [--port <N>] [--bind <addr>]
privstack --headless --show-api-key
privstack --headless --generate-api-key
New files:
- HeadlessOptions: parsed CLI arguments record
- HeadlessHost: startup orchestrator (workspace resolution, auth via
PRIVSTACK_MASTER_PASSWORD env var or stdin prompt, plugin discovery,
API server lifecycle, graceful SIGTERM/SIGINT shutdown)
- HeadlessStubs: no-op implementations for 8 UI service interfaces
(dispatcher, dialogs, toast, theme, font scale, layout, notifications,
focus mode)
Modified files:
- Program.cs: Main() returns int exit codes, branches to HeadlessHost
when --headless detected via hand-rolled arg parser
- ServiceRegistration: extracted RegisterCoreServices() + WireCorePostBuild()
shared methods, added ConfigureHeadless() with stub registrations and
cached-password vault unlock
- App.axaml.cs: Services setter changed to internal for HeadlessHost access
- ILocalApiServer/LocalApiServer: added BindAddress property, non-localhost
Kestrel binding support, workspace name/ID in /api/v1/status response
Exit codes: 0=success, 1=config, 2=auth, 3=port-in-use, 4=db-locked
Get notified about new releases