# Role: Senior .NET Developer # Goal: Build a Transparent & Pilot-Ready ASP.NET Core latest Sync App ## Context: A prototype for Microsoft Graph Calendar Sync that makes the background process visible via a Web Dashboard. ## Core Tech: - .NET 10.0 MVC + EF Core SQLite. - Microsoft.Identity.Web (Confidential Client flow). ## Key Requirements: 1. **Database Schema (SQLite):** - 'UserConfigs': Tracks 'UserId', 'Email', 'SubscriptionId', 'Expiration', 'LastDeltaToken'. - 'WebhookLogs': Tracks 'Id', 'ReceivedAt', 'Payload' (raw JSON), 'Type' (Notification/Lifecycle). 2. **Webhook Controller ('/api/notifications'):** - Implement '/listen' and '/lifecycle'. - **Crucial:** Log every incoming request body into 'WebhookLogs' before processing. - Return 'validationToken' as text/plain (not JSON). 3. **Management Dashboard ('/Sync/Dashboard'):** - Create a Razor View that displays: - A table of all rows in 'UserConfigs'. - A table of the last 20 rows in 'WebhookLogs' (ordered by newest). - A "Sync Now" button that triggers a manual Delta query for a specific user. 4. **Background Logic:** - 'SubscriptionManagerService': A background worker that checks for expiring subscriptions every 12 hours. - When a webhook hits, trigger a 'SyncTask' that performs the Delta query and writes updates to the 'SyncResults.xlsx' file. 5. **Transparency/Feedback:** - Use 'ILogger' to print the specific Subject and ChangeType of every event processed to the console. - Ensure the 'validationToken' handshake is logged so I can see it succeed. ## Instructions: - Provide placeholders for ClientId, TenantId, ClientSecret, and BaseUrl. - Ensure the app can run on macOS using 'dotnet run'. ## Implementation Status (Updated: 2026-02-20) ### Completed Tasks: 1. **Project Initialization:** - Created ASP.NET Core MVC project targeting .NET 10.0. - Added required NuGet packages: - `Microsoft.EntityFrameworkCore.Sqlite` - `Microsoft.EntityFrameworkCore.Design` - `Microsoft.Identity.Web` - `ClosedXML` (for Excel) - `Microsoft.Graph` & `Azure.Identity` 2. **Database Implementation:** - Created `UserConfig` and `WebhookLog` models in `Models/`. - Configured `AppDbContext` in `Data/`. - Configured SQLite connection string in `appsettings.json`. - Added logic in `Program.cs` to automatically ensure the database is created (`EnsureCreated`). 3. **Webhook Handling:** - Implemented `WebhookController` (`/api/notifications`). - `[HttpPost("listen")]` and `[HttpPost("lifecycle")]` endpoints created. - **Validation:** Handles `validationToken` query parameter and returns it as `text/plain`. - **Logging:** Logs all request payloads to `WebhookLogs` table before processing. 4. **Sync Logic & Excel Reporting:** - Implemented `SyncService` (`ISyncService`) to encapsulate synchronization logic. - Configured `GraphServiceClient` with `ClientSecretCredential`. - Added logic to perform (simulated) Delta queries. - Implemented `ClosedXML` logic to write/append sync results to `SyncResults.xlsx`. 5. **Dashboard:** - Created `SyncController` with `Dashboard` action. - Implemented Razor View `Views/Sync/Dashboard.cshtml` displaying: - `UserConfigs` table. - Last 20 `WebhookLogs`. - "Sync Now" button triggering manual sync via `SyncService`. 6. **Background Services:** - Implemented `SubscriptionManagerService` as an `IHostedService`. - Checks for expiring subscriptions every 12 hours (and on startup). 7. **Configuration:** - Updated `appsettings.json` with placeholders for Azure AD credentials (`ClientId`, `TenantId`, `ClientSecret`, `BaseUrl`). ### How to Run: 1. Navigate to the project directory: ```bash cd GraphCalendarSync ``` 2. Update `appsettings.json` with your actual Azure AD credentials. 3. Run the application: ```bash dotnet run ``` 4. Access the dashboard at `https://localhost:7197/Sync/Dashboard` (port may vary, check console output).