Starface requires every contact to be assigned to a tag.
- Load tag IDs when fetching address books (folder/all for central,
folder/private for personal)
- Include tags array in POST /contacts body
- Debug log all discovered tags for troubleshooting
Important: Existing profiles need to reload address books (edit
profile -> load address books -> save) to pick up the tag IDs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Generated programmatically, no external ICO file needed.
Blue rounded square with white person silhouette and green/yellow
sync arrows. Used for main window title bar and system tray.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SetupTrayIcon was called on every RefreshProfileList, creating
a new NotifyIcon each time. Split into SetupTrayIcon (once) and
UpdateTrayMenu (on refresh).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Log the full request body and response when POST /contacts fails
so we can see why new contacts are not being created.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deletes all contact mappings and resets LastSync timestamp.
Next sync will re-match all contacts fresh without creating
duplicates (thanks to the duplicate detection in sync engine).
No contacts are deleted on either side.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three-phase sync approach:
1. Process existing mappings (detect changes on both sides,
handle conflicts with configurable winner)
2. Sync unmapped Outlook contacts to Starface with duplicate
check (match by email, name+company, name, phone)
3. Sync unmapped Starface contacts to Outlook with duplicate check
Key improvements:
- Duplicate detection before creating: checks email, name+company,
name, and phone number with normalization
- Matched duplicates get linked instead of re-created
- Conflict resolution when both sides changed
- Dead mappings (both sides deleted) get cleaned up
- Each contact logged individually with direction indicator
- Address book switch works: old mappings get cleaned, contacts
re-matched against new book
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Read mapping: Match by 'name' field instead of 'displayKey' because
many fields use USER_DEFINED as displayKey (street, city, state,
comment). Actual name fields: firstname, familyname, company, phone,
mobile, homephone, fax, e-mail, url, comment, street, city, postcode,
state, country.
Write mapping: Use correct 4-block structure (contact, address,
telephone, email) with proper resourceKey values matching the
Starface internal format.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The contacts list endpoint only returns summaryValues/phoneNumbers.
Now fetch each contact individually via GET /contacts/{id} to get
all fields (blocks/attributes). Also log the detail JSON structure
so we can verify the field mapping is correct.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Logs the first contact from Starface API response into the sync
log so we can see the actual JSON structure and fix field mapping.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Starface API:
- Handle both array and object responses from /contacts endpoint
- Try common wrapper fields (items, contacts, data, results)
Outlook contacts:
- Add FindFolderByPath that matches exact FolderPath property
- Fallback to Namespace.Folders navigation if store lookup fails
- Fallback: try reading contact fields even if Class != 40
- Add debug logging for folder path and item count
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The NuGet package Microsoft.Office.Interop.Outlook v15 tried to
load Office v15 PIA which fails on Office 2016/2019/2024 (v16).
Switch to dynamic COM (late binding) which works with ANY Outlook
Classic version without needing a specific Interop DLL. All Outlook
properties and methods are accessed via dynamic dispatch.
Also use 1-based COM collection indexing instead of foreach to
avoid COM enumerator issues.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Try GetActiveObject first, then Activator.CreateInstance as fallback
- Use Type.GetTypeFromProgID for version-independent COM activation
- Clear error message explaining possible causes including New Outlook
- NuGet Interop v15 is fine - it's the assembly version, works with
all Outlook versions (2013-2024) via COM interface compatibility
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Scan all stores recursively instead of only the default folder
- Properly release COM objects to avoid leaks
- Better error handling with debug output per store/folder
- Show error message if Outlook is not reachable
- Fallback to default contacts folder if recursive scan finds nothing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace Outlook folder ComboBox with TextBox + Browse button
that opens a TreeView-based folder browser dialog
- Add per-user settings stored in %AppData% (not HKLM)
with option to start minimized (System Tray only)
- Add Settings button to main window
- Settings are per-user, independent of profiles
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Important for Terminal Server / multi-user environments where
the setup is run once by an admin.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Declare ErrorCode variable in InitializeSetup function
- Remove orphan var block at end of Code section
- Fix sed pattern in release.sh to only match version inside quotes
- Restore AboutForm.cs variable name damaged by previous sed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prompts for username and password at script start instead
of requiring a pre-configured API token.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Handles version bump, build, Inno Setup via Docker, git tag,
push, Gitea release creation and setup.exe upload in one step.
Usage: ./release.sh 0.1.0.0 "Release description"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reorder installer section with Docker first (recommended),
Windows second, Wine as fallback. Add one-liner build command.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add .NET SDK install, build and Inno Setup instructions for
both Windows and Linux (Docker or Wine).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Target net8.0-windows instead of net4.8
- EnableWindowsTargeting for Linux build
- Replace Marshal.GetActiveObject with P/Invoke (not in .NET 8)
- Use NuGet package for Outlook Interop instead of local DLL ref
- Update Inno Setup script for .NET 8 runtime check
- Builds successfully on Linux, runs on Windows
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the Office Web Add-in with a native Windows application.
The web add-in required Exchange/M365 for registration which is
not available in all customer environments (standalone Office,
POP/IMAP only).
The new app:
- Uses COM Interop to access Outlook contacts directly
- Communicates with Starface REST API (accepts self-signed certs)
- Runs as System Tray app with optional auto-sync
- Profile-based config stored in %AppData%
- No webserver, no certificates, no Exchange, no M365 needed
- Inno Setup installer for clean MSI-style deployment
- Works with any Outlook version (Classic and New)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove Exchange PowerShell option. Outlook add-ins are registered
per Microsoft 365 account via browser sideload. Each user must
add the add-in once - it then works on all their devices.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The TrustedCatalogs registry approach only works for Word/Excel/
PowerPoint, NOT for Outlook. Outlook add-ins must be registered
via Exchange or manually through OWA.
Setup now offers two paths:
- Exchange Online PowerShell (New-App) for organizations
- Manual sideload via https://aka.ms/olksideload as fallback
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ExportPkcs8PrivateKey() is only available in .NET Core 3.0+
but Windows PowerShell 5.1 uses .NET Framework 4.x.
Switch to PFX export which works on all Windows versions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix PrivateKey null error by using GetRSAPrivateKey() instead of
.PrivateKey which is null for certs created with -Signer
- Replace all Unicode characters (umlauts, arrows, emojis) with
ASCII-safe alternatives so output renders correctly on any
Windows console regardless of codepage
- Add explanation in setup why Starface URL is needed (CA import)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
After cloning the repo the installer can be run directly
without needing npm/webpack installed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add dist/ to .gitignore as well since both directories
contain generated content that should not be tracked.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>