Add Windows support for Database Encryption and NSIS deployment#31
Add Windows support for Database Encryption and NSIS deployment#31xnodeoncode merged 13 commits intomainfrom
Conversation
Add Database Encryption and NSIS Deployment for Windows
There was a problem hiding this comment.
Pull request overview
Adds Windows support for database encryption by introducing a platform keychain abstraction (Windows DPAPI + existing Linux secret-tool), updates Electron packaging to use NSIS on Windows, and includes EF Core startup/performance improvements (compiled model + publish/startup tuning).
Changes:
- Introduce
IKeychainServiceand a Windows DPAPI-backedWindowsKeychainService, and wire keychain selection into both SimpleStart and Professional. - Optimize encrypted DB connection startup by pre-deriving SQLCipher raw keys and adding EF Core compiled model artifacts + documentation.
- Switch SimpleStart Windows packaging from portable to NSIS and adjust restore/encryption workflows to reduce file-lock issues.
Reviewed changes
Copilot reviewed 59 out of 59 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Documentation/Database-Management-Guide.md | Documents EF Core migrations workflow + compiled model regeneration steps. |
| Aquiis.code-workspace | Adds PowerShell working directory setting. |
| 5-Aquiis.Professional/Shared/Services/DatabaseBackupService.cs | Simplifies health-check path (removes redundant connectivity check). |
| 5-Aquiis.Professional/Program.cs | Registers IKeychainService with Windows/Linux implementation selection. |
| 4-Aquiis.SimpleStart/electron.manifest.json | Switches Windows build target to NSIS + installer options and artifact naming. |
| 4-Aquiis.SimpleStart/Shared/Services/DatabaseBackupService.cs | Simplifies health-check path (removes redundant connectivity check). |
| 4-Aquiis.SimpleStart/Program.cs | Reorders Electron initialization vs restore handling; improves restore swap robustness (Windows handles/WAL cleanup). |
| 4-Aquiis.SimpleStart/Features/Administration/Settings/Pages/DatabaseSettings.razor | Encrypt/decrypt now operates on backups directly to avoid copying/locking the live DB file. |
| 4-Aquiis.SimpleStart/Extensions/WebServiceExtensions.cs | Adds Windows keychain retrieval path and raw-key pre-derivation at startup; reduces verbose logging. |
| 4-Aquiis.SimpleStart/Extensions/ElectronServiceExtensions.cs | Adds Windows keychain retrieval path and raw-key pre-derivation at startup; reduces verbose logging. |
| 4-Aquiis.SimpleStart/Assets/install-desktop-integration.sh | Improves usage guidance and ensures AppImage is executable; updates desktop entry metadata. |
| 4-Aquiis.SimpleStart/Aquiis.SimpleStart.csproj | Forces multi-file publish and enables publish-time perf settings to avoid single-file extraction delays. |
| 2-Aquiis.Application/Services/DatabaseUnlockService.cs | Switches keychain dependency from Linux-specific service to IKeychainService. |
| 2-Aquiis.Application/Services/DatabasePreviewService.cs | Switches keychain dependency from Linux-specific service to IKeychainService. |
| 2-Aquiis.Application/Services/DatabasePasswordService.cs | Switches keychain dependency from Linux-specific service to IKeychainService. |
| 1-Aquiis.Infrastructure/Services/WindowsKeychainService.cs | New: Windows DPAPI-backed key storage implementation. |
| 1-Aquiis.Infrastructure/Services/LinuxKeychainService.cs | Implements IKeychainService (previously concrete-only). |
| 1-Aquiis.Infrastructure/Services/DatabaseEncryptionService.cs | Uses IKeychainService; adds Windows file-handle/pool-release mitigations and explicit SQLCipher params for decrypt/verify. |
| 1-Aquiis.Infrastructure/Interfaces/IKeychainService.cs | New: platform abstraction for secure key storage. |
| 1-Aquiis.Infrastructure/Data/SqlCipherConnectionInterceptor.cs | Supports raw-key format and enforces WAL/synchronous PRAGMAs on connection open. |
| 1-Aquiis.Infrastructure/Data/CompiledModels/ApplicationDbContextAssemblyAttributes.cs | Adds compiled model discovery attribute (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/ApplicationDbContextModel.cs | Compiled model runtime model (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/ApplicationDbContextModelBuilder.cs | Compiled model builder wiring (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/ApplicationScreeningEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/CalendarEventEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/CalendarSettingsEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/ChecklistEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/ChecklistItemEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/ChecklistTemplateEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/ChecklistTemplateItemEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/DatabaseSettingsEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/DocumentEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/InspectionEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/InvoiceEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/LeaseEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/LeaseOfferEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/MaintenanceRequestEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/NoteEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/NotificationEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/NotificationPreferencesEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/OrganizationEmailSettingsEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/OrganizationEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/OrganizationSMSSettingsEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/OrganizationSettingsEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/OrganizationUserEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/PaymentEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/PropertyEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/ProspectiveTenantEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/RentalApplicationEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/RepairEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/SchemaVersionEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/SecurityDepositDividendEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/SecurityDepositEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/SecurityDepositInvestmentPoolEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/TenantEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/TourEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/UserProfileEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Data/CompiledModels/WorkflowAuditLogEntityType.cs | Compiled model entity type (auto-generated). |
| 1-Aquiis.Infrastructure/Aquiis.Infrastructure.csproj | Adds ProtectedData package for Windows DPAPI support. |
| if (_encryptionKey.StartsWith("x'", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| // Pre-derived raw key — SQLCipher loads it directly, no PBKDF2 (~0 ms) | ||
| cmd.CommandText = $"PRAGMA key = \"{_encryptionKey}\";"; | ||
| cmd.ExecuteNonQuery(); | ||
| } |
There was a problem hiding this comment.
In the raw-key path (when _encryptionKey starts with "x'"), the interceptor sets only PRAGMA key and skips the SQLCipher 4 cipher parameters (page size, kdf_iter, hmac/kdf algorithms). Since this PR now pre-derives a raw key at startup, encrypted DB connections will typically go through this branch, which can lead to failed opens if the library doesn't auto-detect the DB's cipher settings (notably on Windows, per the decryption code comments). Apply the same SQLCipher PRAGMAs for both raw-key and passphrase paths (either after setting the key or in a common block).
| /// Performance note: accepts either a plaintext passphrase or a pre-derived raw key in SQLCipher's | ||
| /// "x'hexbytes'" format. Raw keys skip the per-connection PBKDF2 derivation entirely, which | ||
| /// eliminates 20–50 ms of CPU work per connection. Use SqlCipherKeyDerivation.DeriveRawKey() | ||
| /// at startup to produce the raw key from the user's passphrase, then pass it here. |
There was a problem hiding this comment.
The XML doc comment references SqlCipherKeyDerivation.DeriveRawKey(), but there is no such type/method in the repo. This will mislead readers; either add the referenced helper or update the comment to point to the actual derivation logic used in this codebase (e.g., the PrepareEncryptionKey helper in the service extensions).
| _logger.LogInformation("SqliteConnection object created, calling OpenAsync()..."); | ||
| _logger.LogInformation("Password length: {Length} characters", password.Length); | ||
| await encryptedConn.OpenAsync(); |
There was a problem hiding this comment.
Logging the password length is sensitive information that can aid password-guessing and shouldn’t be emitted at Info level. Please remove this log line or downgrade it behind an explicit debug/verbose flag that is off in production.
Add support for database encryption and nsis deployment for Windows.