> ## Documentation Index
> Fetch the complete documentation index at: https://docs.equa.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Microsoft Integration

> Azure AD client-credentials OAuth for Microsoft 365 group management and Graph API access

# SPEC 017 — Microsoft Integration

| Field    | Value                                       |
| -------- | ------------------------------------------- |
| Status   | DRAFT                                       |
| Priority | P2 — Integration                            |
| Backend  | `equa-server/modules/microsoft/`            |
| Frontend | `equa-web/src/shared/helpers/ms/msGraph.ts` |

***

## 1. Feature Purpose

The Microsoft Integration connects Equa organizations to Microsoft 365 via Azure AD. It uses the OAuth 2.0 client credentials flow to obtain application-level access to the Microsoft Graph API, enabling the platform to manage Microsoft 365 groups on behalf of organizations. This powers team provisioning, group membership synchronization, and future SharePoint/Teams integrations without requiring individual user consent.

***

## 2. Current State (Verified)

### 2.1 OAuth Client Credentials Flow

| Detail     | Value                                                                         |
| ---------- | ----------------------------------------------------------------------------- |
| Grant type | `client_credentials` (application-level, no user interaction)                 |
| Authority  | `https://login.microsoftonline.com/{MS_AUTH_TENANT_ID}`                       |
| Scope      | `https://graph.microsoft.com/.default`                                        |
| Library    | `@azure/msal-node` ConfidentialClientApplication                              |
| Env vars   | `MS_AUTH_CLIENT_ID`, `MS_AUTH_TENANT_ID`, `MS_AUTH_SECRET`, `MS_AUTH_ENABLED` |

### 2.2 Graph API Helper

| Detail        | Value                                                             |
| ------------- | ----------------------------------------------------------------- |
| File          | `equa-web/src/shared/helpers/ms/msGraph.ts`                       |
| Client        | `@microsoft/microsoft-graph-client` via `Client.init()`           |
| Auth provider | Passes access token from MSAL into the Graph client auth callback |

### 2.3 Microsoft Group Binding

| Detail    | Value                                                                                     |
| --------- | ----------------------------------------------------------------------------------------- |
| Storage   | `Organizations.microsoftGroup` (uuid field on existing Organizations entity)              |
| Lifecycle | Group ID stored when an organization links to an existing M365 group or creates a new one |
| Usage     | Used to resolve group members, sync membership, and manage group settings via Graph API   |

### 2.4 Backend Module

| Component   | Path                                                           |
| ----------- | -------------------------------------------------------------- |
| Module root | `equa-server/modules/microsoft/`                               |
| Endpoints   | `equa-server/modules/api/src/endpoints/microsoft-endpoints.ts` |

***

## 3. Data Model

The Microsoft integration does not introduce dedicated entities. It relies on a single field on the existing `Organizations` table and the Azure AD tenant for all state.

### Organizations (relevant field)

| Column         | Type | Constraints                         |
| -------------- | ---- | ----------------------------------- |
| microsoftGroup | uuid | nullable — Azure AD group object ID |

### Token Caching

MSAL's `ConfidentialClientApplication` handles in-memory token caching and automatic refresh. No database persistence is required for tokens since the client credentials flow can always obtain a new token from Azure AD without user interaction.

***

## 4. API Endpoints

| Method | Path                                                          | Auth | Description                                            |
| ------ | ------------------------------------------------------------- | ---- | ------------------------------------------------------ |
| GET    | `/api/v1/organizations/:id/microsoft/status`                  | Yes  | Check if MS integration is enabled and group is linked |
| POST   | `/api/v1/organizations/:id/microsoft/link-group`              | Yes  | Associate an existing M365 group with the organization |
| POST   | `/api/v1/organizations/:id/microsoft/create-group`            | Yes  | Create a new M365 group and link it                    |
| DELETE | `/api/v1/organizations/:id/microsoft/unlink-group`            | Yes  | Remove the M365 group association                      |
| GET    | `/api/v1/organizations/:id/microsoft/group`                   | Yes  | Fetch linked group details from Graph API              |
| GET    | `/api/v1/organizations/:id/microsoft/group/members`           | Yes  | List members of the linked M365 group                  |
| POST   | `/api/v1/organizations/:id/microsoft/group/members`           | Yes  | Add a member to the linked M365 group                  |
| DELETE | `/api/v1/organizations/:id/microsoft/group/members/:memberId` | Yes  | Remove a member from the linked M365 group             |
| POST   | `/api/v1/organizations/:id/microsoft/sync-members`            | Yes  | Sync Equa team members to/from M365 group membership   |

***

## 5. Frontend Components

| Component                    | Path                                        | Description                                                    |
| ---------------------------- | ------------------------------------------- | -------------------------------------------------------------- |
| msGraph helper               | `equa-web/src/shared/helpers/ms/msGraph.ts` | Initializes Microsoft Graph client with token auth provider    |
| Settings integration section | `equa-web/src/modules/settings/`            | Organization settings page includes Microsoft group linking UI |

### Frontend Behavior

* **Feature gate** — Microsoft integration UI elements are hidden when `MS_AUTH_ENABLED` is false.
* **No user OAuth** — Since the integration uses client credentials, there is no user-facing OAuth popup. Admins link groups by entering or selecting a group ID.
* **Graph client** — The frontend helper (`msGraph.ts`) creates a Graph client instance; however, in practice most Graph API calls are proxied through the backend to avoid exposing the application secret.
* **Group status display** — Shows linked group name, member count, and last sync time when a group is associated.

***

## 6. Business Rules

1. **Application-level auth** — The client credentials flow grants tenant-wide access; no individual user consent is required. This requires Azure AD admin consent for the app registration.
2. **One group per organization** — Each Equa organization links to at most one M365 group via `Organizations.microsoftGroup`.
3. **Feature flag gating** — All Microsoft endpoints return 404 when `MS_AUTH_ENABLED` is false, preventing accidental exposure.
4. **Token lifecycle** — MSAL handles token acquisition, caching, and refresh internally. Tokens are never persisted to disk or database.
5. **Tenant scoping** — The integration operates within a single Azure AD tenant defined by `MS_AUTH_TENANT_ID`. Multi-tenant support is not implemented.
6. **Group creation defaults** — Newly created M365 groups are configured as private with mail-enabled security group type.
7. **Member sync direction** — Sync is bidirectional: Equa team members are added to the M365 group, and M365 group members without Equa accounts are flagged for invitation.
8. **Unlink preserves group** — Unlinking an M365 group from an Equa organization clears `microsoftGroup` but does not delete the group in Azure AD.
9. **Admin-only operations** — Group linking, unlinking, creation, and member management require organization admin role.
10. **Graph API error handling** — 401/403 from Graph API triggers a token refresh and single retry; persistent failures are surfaced to the user.

***

## 7. Acceptance Criteria

* [ ] Admin can link an existing M365 group to the organization by group ID
* [ ] Admin can create a new M365 group from the Equa settings page
* [ ] Admin can unlink the M365 group; the Azure AD group is not deleted
* [ ] Linked group details (name, description, member count) display correctly
* [ ] Group members list shows current M365 group membership
* [ ] Admin can add a member to the M365 group via the Equa UI
* [ ] Admin can remove a member from the M365 group via the Equa UI
* [ ] Member sync reconciles Equa team members with M365 group membership
* [ ] All Microsoft endpoints return 404 when `MS_AUTH_ENABLED` is false
* [ ] Token refresh is automatic and transparent to the user
* [ ] Non-admin users cannot access Microsoft integration endpoints
* [ ] Graph API errors are surfaced with actionable messages

***

## 8. Risks

| Risk                                                         | Impact                                                     | Mitigation                                                                                      |
| ------------------------------------------------------------ | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| Tenant-wide application permissions                          | Over-privileged access to all tenant resources             | Request minimum Graph API permissions (Group.ReadWrite.All only); audit app registration scopes |
| `MS_AUTH_SECRET` exposure                                    | Full tenant access compromise                              | Store in vault; rotate on schedule; never log or return in API responses                        |
| Single-tenant limitation                                     | Cannot support organizations in different Azure AD tenants | Document limitation; plan multi-tenant app registration if demand arises                        |
| Azure AD admin consent required                              | Onboarding friction for new tenants                        | Provide clear setup documentation; consider admin consent URL generator                         |
| In-memory token cache lost on restart                        | Minor latency spike on first post-restart call             | Acceptable trade-off; MSAL re-acquires tokens automatically                                     |
| Graph API rate limits (10 000 requests / 10 minutes per app) | Sync failures for large groups                             | Implement batching and throttle-aware retry with `Retry-After` header                           |
| M365 group deleted externally                                | Stale `microsoftGroup` reference, API errors               | Health check on group status; clear stale references on 404                                     |
| Member sync conflicts (user exists in M365 but not in Equa)  | Incomplete sync, orphaned members                          | Flag unmatched members for admin review rather than auto-creating accounts                      |
