feat(api): add microsoft sign-in and outlook mailbox sync - #73
Conversation
…pdating environment configurations. Refactor Google sync services to utilize a unified mailbox API client. Update README and .env.example to reflect new authentication options and instructions for Microsoft integration.
…l request processes; add pr-title.sh script for automated PR title generation based on Conventional Commit standards; enhance auto-pr workflow to utilize the new script for title management.
…odify auto-pr workflow to create pull requests directly instead of drafts, and enhance title management for better integration with commit subjects and changelog entries.
… for CI checks, integration test requirements, and how to bypass hooks when necessary.
…ls and correct tool count in documentation.
There was a problem hiding this comment.
6 issues found and verified against the latest diff
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/api/src/sync/mailbox-sync.service.ts">
<violation number="1" location="apps/api/src/sync/mailbox-sync.service.ts:89">
P3: Thrown Microsoft syncs are mislabeled as `google_sync` telemetry because this call now reports every provider through a helper with a hard-coded Google error source; make the telemetry event provider-aware so Outlook failures remain distinguishable.</violation>
</file>
<file name="packages/auth/src/env.ts">
<violation number="1" location="packages/auth/src/env.ts:36">
P1: Microsoft sign-in is silently disabled when the API runs through Turborepo with deployment-provided environment variables, because `microsoftCredentials()` sees no client credentials and returns `undefined`; a configured tenant is also ignored. The Microsoft variables should be added to the applicable root and API Turborepo pass-through lists.</violation>
</file>
<file name="apps/api/src/microsoft/microsoft.router.ts">
<violation number="1" location="apps/api/src/microsoft/microsoft.router.ts:34">
P1: An authenticated user can delete another user's Outlook-synced messages when both mailboxes contribute messages to the same thread, because this mutation invokes a purge that removes the whole thread for any matching child message. The purge should delete only the caller's messages and remove a thread only when no messages remain, or otherwise enforce thread ownership.</violation>
</file>
<file name="apps/api/src/mailbox/thread-writer.service.ts">
<violation number="1" location="apps/api/src/mailbox/thread-writer.service.ts:97">
P1: Unknown inbound mail is permanently omitted when it arrives before the user's reply, even with auto-create enabled. Deferring company/contact creation until a reply is reasonable, but the inbound message needs to be retained or replayed once the later outbound message makes the thread eligible; otherwise O365 threads lose their opening messages.</violation>
</file>
<file name="apps/api/src/google/gmail-mime.ts">
<violation number="1" location="apps/api/src/google/gmail-mime.ts:60">
P1: Replies containing multiple message IDs in `In-Reply-To` receive a malformed thread key instead of the first referenced message ID, causing those Gmail messages to split from the shared CRM thread. Extract one message ID from `In-Reply-To` before calling `rootMessageIdFrom` (or make the shared helper parse the field as a list).</violation>
</file>
<file name=".github/workflows/pr-title.yml">
<violation number="1" location=".github/workflows/pr-title.yml:22">
P1: A pull request can change `.github/scripts/pr-title.sh`, and this workflow executes that checked-out file with `GH_TOKEN` and `ANTHROPIC_API_KEY`, creating a credential-exfiltration path. Run only a trusted script from the base commit and fetch PR refs separately, rather than executing code from the PR merge ref.</violation>
</file>
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
| const microsoftCredentials = (): | ||
| | { clientId: string; clientSecret: string; tenantId: string } | ||
| | undefined => { | ||
| const credentials = pair("MICROSOFT_CLIENT_ID", "MICROSOFT_CLIENT_SECRET"); |
There was a problem hiding this comment.
P1: Microsoft sign-in is silently disabled when the API runs through Turborepo with deployment-provided environment variables, because microsoftCredentials() sees no client credentials and returns undefined; a configured tenant is also ignored. The Microsoft variables should be added to the applicable root and API Turborepo pass-through lists.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/auth/src/env.ts, line 36:
<comment>Microsoft sign-in is silently disabled when the API runs through Turborepo with deployment-provided environment variables, because `microsoftCredentials()` sees no client credentials and returns `undefined`; a configured tenant is also ignored. The Microsoft variables should be added to the applicable root and API Turborepo pass-through lists.</comment>
<file context>
@@ -2,30 +2,46 @@ import "@crm/env/load";
+const microsoftCredentials = ():
+ | { clientId: string; clientSecret: string; tenantId: string }
+ | undefined => {
+ const credentials = pair("MICROSOFT_CLIENT_ID", "MICROSOFT_CLIENT_SECRET");
+ if (!credentials) return undefined;
+
</file context>
|
|
||
| @Mutation() | ||
| async purgeSyncedData(@Ctx() ctx: AuthedTrpcContext) { | ||
| return this.connection.purgeSyncedData(ctx.user.id); |
There was a problem hiding this comment.
P1: An authenticated user can delete another user's Outlook-synced messages when both mailboxes contribute messages to the same thread, because this mutation invokes a purge that removes the whole thread for any matching child message. The purge should delete only the caller's messages and remove a thread only when no messages remain, or otherwise enforce thread ownership.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/api/src/microsoft/microsoft.router.ts, line 34:
<comment>An authenticated user can delete another user's Outlook-synced messages when both mailboxes contribute messages to the same thread, because this mutation invokes a purge that removes the whole thread for any matching child message. The purge should delete only the caller's messages and remove a thread only when no messages remain, or otherwise enforce thread ownership.</comment>
<file context>
@@ -0,0 +1,60 @@
+
+ @Mutation()
+ async purgeSyncedData(@Ctx() ctx: AuthedTrpcContext) {
+ return this.connection.purgeSyncedData(ctx.user.id);
+ }
+
</file context>
| error instanceof Error ? error.stack : String(error), | ||
| ); | ||
|
|
||
| syncError({ error, source: row.source }); |
There was a problem hiding this comment.
P3: Thrown Microsoft syncs are mislabeled as google_sync telemetry because this call now reports every provider through a helper with a hard-coded Google error source; make the telemetry event provider-aware so Outlook failures remain distinguishable.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/api/src/sync/mailbox-sync.service.ts, line 89:
<comment>Thrown Microsoft syncs are mislabeled as `google_sync` telemetry because this call now reports every provider through a helper with a hard-coded Google error source; make the telemetry event provider-aware so Outlook failures remain distinguishable.</comment>
<file context>
@@ -0,0 +1,116 @@
+ error instanceof Error ? error.stack : String(error),
+ );
+
+ syncError({ error, source: row.source });
+ }
+ }
</file context>
…details on the promotion pull request and the role of the release pull request. Modify release workflow to ensure proper tagging and streamline the promotion of changes from main to release. Enhance CI workflows to better handle pull request retargeting and title management.
…ronment configurations and updating the purge logic for both Google and Microsoft data. Refactor email message handling to improve thread management and ensure proper cleanup of synced data. Introduce new tests for mailbox purging and syncing functionality.
Opened automatically when
lewis/better-auth-o365was pushed.This pull request is squashed onto
main, so its title becomes the commit subject and the changelog line. Make it a Conventional Commit —feat(app): …,fix(api): …— before marking it ready for review, which is when the title is checked.The type decides the version bump:
featis a minor,fix/perf/refactor/docsare a patch, a trailing!is a major, andchore/ci/test/build/stylerelease nothing at all.Summary by cubic
Add Microsoft 365 sign-in and Outlook mail sync, unify Gmail/Calendar with a shared mailbox sync used by both providers, and add a purge for synced mailbox data. Also improve thread handling and streamline CI/releases with auto PR titles, retargeting, and a main→release promotion flow.
New Features
Mail.Read).MailboxModule(tokens, matching, thread writer, HTTP client) now powers Gmail, Calendar, and Outlook; email timeline links to Gmail or Outlook with provider labels./internal/sync/mailboxes.check-types,lint, andtest; PR titles auto-generated from the diff via.github/scripts/pr-title.sh; PRs opened againstreleaseare retargeted tomain; a promotion workflow opens a PR frommainintorelease; releases run from thereleasebranch.Migration
MICROSOFT_CLIENT_ID,MICROSOFT_CLIENT_SECRET, and optionalMICROSOFT_TENANT_ID(defaults tocommon); add redirect<API_URL>/api/auth/callback/microsoft./internal/sync/mailboxes.outlookMessageIdandoutlookWebLink..env.exampleand docs for updated configuration and scope details.Written for commit 7aad9a7. Summary will update on new commits.