--- title: T02 summary status: done files: - Models/Correspondence.cs - JobTrackerApi/Controllers/GmailController.cs - JobTrackerApi/Controllers/CorrespondenceController.cs - JobTrackerApi/Program.cs - JobTrackerApi.Tests/GmailControllerTests.cs observability_surfaces: - POST /api/gmail/import - POST /api/gmail/import-thread - persisted Correspondence.ExternalThreadId / ExternalFrom / ExternalTo fields - JobTrackerApi.Tests/GmailControllerTests.cs repeat-import coverage verification: - $HOME/.dotnet/dotnet build JobTrackerApi/JobTrackerApi.csproj - docker run --rm -v "$PWD":/src -w /src mcr.microsoft.com/dotnet/sdk:9.0 bash -lc '...dotnet test /tmp/gmailtests/GmailTests.csproj...' --- Extended correspondence persistence and Gmail import continuity for S01. ## What changed - `Models/Correspondence.cs` - added `ExternalThreadId` - added `ExternalFrom` - added `ExternalTo` - `JobTrackerApi/Controllers/GmailController.cs` - single-message import now returns `GmailImportMessageResultDto` with `Imported`, `Skipped`, `MessageId`, `ThreadId`, and the imported/existing `Correspondence` - repeat single-message imports now report `Imported=0` / `Skipped=1` instead of returning a bare correspondence record - imported Gmail messages now persist thread id plus raw sender/recipient metadata - `JobTrackerApi/Controllers/CorrespondenceController.cs` - create request now accepts optional external message/thread/from/to metadata so the correspondence surface stays consistent with enriched imports - `JobTrackerApi/Program.cs` - added SQLite compatibility guards for `Correspondences.ExternalThreadId`, `Correspondences.ExternalFrom`, and `Correspondences.ExternalTo` - added MySQL compatibility guards for the same columns - `JobTrackerApi.Tests/GmailControllerTests.cs` - added repeat single-message import coverage - added repeat thread import coverage - retained ranking and owned-job scope coverage from T01 ## Verification - Native API build passed with `$HOME/.dotnet/dotnet build JobTrackerApi/JobTrackerApi.csproj` - Isolated Gmail controller tests passed in Docker (`5 passed`) ## Verification Evidence | # | Command | Exit Code | Verdict | Duration | |---|---------|-----------|---------|----------| | 1 | `$HOME/.dotnet/dotnet build JobTrackerApi/JobTrackerApi.csproj` | 0 | ✅ pass | ~1.2s | | 2 | `docker run --rm -v "$PWD":/src -w /src mcr.microsoft.com/dotnet/sdk:9.0 bash -lc '...dotnet test /tmp/gmailtests/GmailTests.csproj...'` | 0 | ✅ pass | not recorded | ## Diagnostics - Inspect persisted `Correspondence` rows for `ExternalMessageId`, `ExternalThreadId`, `ExternalFrom`, and `ExternalTo` to confirm Gmail imports keep thread identity plus sender/recipient labels. - Hit `POST /api/gmail/import` twice with the same Gmail message id to confirm the duplicate-safe `Imported`/`Skipped` contract. - Hit `POST /api/gmail/import-thread` twice with the same thread payload to confirm repeat imports skip already-linked message ids instead of duplicating correspondence. - Read `JobTrackerApi.Tests/GmailControllerTests.cs` for the durable expected behavior around repeat single-message and repeat thread imports. ## Important caveat The repository’s main `JobTrackerApi.Tests` project still had unrelated pre-existing compile failures outside Gmail tests when this task finished, so the exact planned command `dotnet test JobTrackerApi.Tests/JobTrackerApi.Tests.csproj --filter GmailControllerTests` remained blocked at that point by broader test drift. Gmail coverage itself passed when isolated.