Flush WAL files on graceful shutdown
Details
Add checkpoint() methods to EntityStore, EventStore, BlobStore,
VaultManager, and DatasetStore. Call all of them from
privstack_shutdown() before dropping the handle.
Previously, shutdown just dropped the handle without checkpointing,
leaving WAL files on disk. On next startup this produced warnings like:
[StorageDiag] data.entities.duckdb.wal: WAL EXISTS! size=210638
DuckDB's implicit drop doesn't guarantee WAL flush, so an explicit
CHECKPOINT is needed for clean shutdown.
Make Duncan chat input multi-line with auto-grow
Details
- Enable AcceptsReturn + TextWrapping on ChatInputBox so users can compose
multi-line messages (grows up to ~10 visible lines / 200px max height,
scrollable beyond that)
- Move Send button below the text box, right-aligned
- Intercept Enter via tunnel-phase KeyDown handler to send message (bypassing
AcceptsReturn's newline insertion); Shift+Enter inserts a newline as expected
Improve text selection contrast, theme editor UX, and Duncan panel shadow
Details
- Halve ThemeSelection opacity across all 7 themes for better text readability
when selecting text (was too dark/saturated, obscuring selected text)
- Add global SelectableTextBlock SelectionBrush style in PrivStackTheme.axaml
so Duncan chat and all selectable text blocks use the theme selection color
- Widen theme editor dialog (1100→1300px) with redesigned header: proper title,
subtitle description, cleaner two-row layout with name input separated from
action buttons
- Add Text Selection and Highlights preview sections to ThemePreviewPanel:
simulated selection overlay, interactive SelectableTextBlock, and all 6
highlight colors (Yellow, Blue, Green, Pink, Purple, Orange) as preview chips
- Add subtle layered drop shadow to Duncan AI chat panel for better visual
separation from content area
Autofocus biometric: activate app before Touch ID and fix timing
Details
The Touch ID system dialog wasn't getting foreground focus because:
1. Biometric was triggered in OnDataContextChanged (before the window
was even visible/activated)
2. The app wasn't explicitly activated before calling LAContext
Fix: Call [NSApp activateIgnoringOtherApps:YES] via ObjC runtime before
evaluatePolicy (DEBUG) and SecItemCopyMatching (RELEASE) to ensure the
app is the active application when Touch ID triggers. This is what
Electron-based apps like VS Code do to get the system biometric dialog
to appear with proper foreground focus.
Also moved biometric init from UnlockView.OnDataContextChanged to
UnlockWindow.OnOpened (after Activate()), ensuring the window is fully
shown and activated before triggering the biometric prompt.
When biometric is available, focus the biometric button instead of the
password box in both UnlockView and SensitiveUnlockOverlay, so users
can press Enter/Space to retry biometric without clicking.
Gate FFI eprintln! logs by PRIVSTACK_LOG_LEVEL
Details
Add FFI_LOG_LEVEL atomic + ffi_error!/ffi_warn!/ffi_info!/ffi_debug!
macros that check the level before printing. privstack_init() reads
PRIVSTACK_LOG_LEVEL env var (error/warn/info/debug) and configures both
the FFI macros and the tracing subscriber filter.
Replaced all 111 raw eprintln! calls across 9 FFI source files with
level-appropriate macros:
- ffi_debug: DB opening, peer ID loading, store init, sync lifecycle
- ffi_info: cloud sync summaries, major lifecycle events
- ffi_warn: corrupt files, poison recovery, non-critical failures
- ffi_error: actual operation failures, panics
android_log() on non-Android platforms now gates output by mapping
the level string to FFI_LOG_LEVEL before printing.
Running with --warn now silences INFO/DEBUG output from both the C#
Serilog layer and the Rust FFI layer.
Get notified about new releases