Add enterprise policy: TOML config, enforcement, and audit logging
Details
Enterprise policy system for headless server deployments:
- EnterprisePolicy: TOML-based config with optional ECDSA P-256 signature
verification to prevent tampering. Supports [plugins], [network], [api],
and [audit] sections with an [authority] signing block.
- PolicyEnforcer: Three enforcement points:
1. Plugin allowlist/blocklist — restricts which plugins can load via
WorkspacePluginConfig's existing whitelist mechanism
2. Network CIDR filtering — ASP.NET Core middleware that blocks requests
from IPs outside allowed CIDR ranges
3. TLS requirement — blocks server startup if policy requires TLS but
it's not configured
- AuditLogger: JSON Lines file writer at admin-controlled path. Logs API
requests (method, path, status, IP, duration) with configurable level
filtering (all/write/auth). Records policy and auth events.
- HeadlessHost: Loads policy before plugin discovery, applies plugin
restrictions, injects network + audit middleware, validates TLS
requirement. --setup-policy flag allows interactive policy configuration.
Add TLS support: manual certificates and Let's Encrypt
Details
LocalApiServer now supports HTTPS via two modes:
1. Manual certificate — load PFX/P12 or PEM+key files directly.
Configured via HeadlessConfig.Tls with mode=Manual.
2. Let's Encrypt (ACME) — automatic free certificate provisioning
via LettuceEncrypt. Requires a public domain and port 80 for
HTTP-01 challenges. Certificates are persisted to disk and
auto-renewed.
Architecture: TlsOptions model lives in PrivStack.Services (shared).
LettuceEncrypt NuGet (1.3.3) is only in PrivStack.Server — the Desktop
never activates it. LocalApiServer exposes OnConfigureServices,
OnConfigureKestrel, and OnConfigureApp hooks so the Server project can
inject LettuceEncrypt without adding the dependency to Services.
Setup wizard now offers both TLS modes interactively. The --setup-tls
flag allows re-configuring TLS independently of the full setup wizard.
Add inline field validation to Calendar event editor (BUG #66)
Details
Replace bottom-of-form error messages with inline validation:
- Title field: red border + "Title is required." message below field
- End time fields: red border around date/time group + inline error
message when end time is before start time
- General ValidationError kept at bottom for read-only and save errors
Add HasTitleError, HasEndTimeError, EndTimeErrorMessage properties to
EventEditorViewModel. Errors clear on form reset and re-validation.
New ValidationConverters.ErrorBorderThickness converter (bool → Thickness).
Add collapsible sidebar to Calendar plugin (BUG #68)
Details
Replace static Border sidebar with shared PluginSidebar control from
PrivStack.UI.Adaptive. Sidebar now has collapse/expand toggle with
smooth animation, resizable width, and consistent behavior matching
Contacts, Snippets, and RSS plugins.
- Add IsCalendarSidebarCollapsed property to CalendarViewModel
- Move sidebar content into PluginSidebar.SidebarContent slot
- Move "+ New Event" button into PluginSidebar.FooterContent slot
- Calendar sources, mini calendar, and quick add all inside sidebar
Clean up GitHub project sync data model
Details
- Remove duplicate GitHubProjectItemLabel DTO; reuse GitHubLabel
directly on GitHubProjectItem.ContentLabels to eliminate unnecessary
type conversion in the mapper
- Add typed accessors on TaskItem for project-specific custom fields:
GitHubProjectSourceId, GitHubProjectItemNodeId, GitHubProjectStatus
- Extract GetCustomFieldString helper to DRY the JsonElement unboxing
pattern shared by GitHubUrl and the new accessors
- Simplify HasProjectStatusChanged to use the typed accessor
Get notified about new releases