@codex review
This PR closes two of the five umbrella bugs in MCPG-209 that together broke user lifecycle event delivery from FusionAuth to the admin app for every tenant we've ever provisioned:
eventConfiguration.events: {}. So no webhook of any kind — SCIM or otherwise — has ever fired for any customer tenant.The new tenant PATCH reuses the same `resolveWebhookProvisioningAuth` result as the webhook upserts (tenant key with admin fallback). Tenant-scoped PATCHes of `eventConfiguration` work with the tenant API key, so no privilege escalation.
@codex review
@codex review
Codex Review: Didn't find any major issues. :tada:
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
While debugging MCPG-196 ("SCIM provisioning fails for new and existing users in Okta integration"), we found that the Okta→Composio user provisioning flow is gated on five stacked, independent bugs, not one. Fixing only the surface symptom (the 400 from FusionAuth) leaves users invisible to the admin app even after FA accepts them.
This umbrella tracks four of the five fixes (Bugs 1, 3, 4, 5). The fifth — Bug 2, "Okta SCIM connector OAuth2 Client Credentials grant has no Scope field" — is already covered by MCPG-189 / PR #479 and is not duplicated here.
This umbrella supersedes the engineering work needed to resolve MCPG-196. Once this umbrella's PRs merge and the backfill runs, MCPG-196 can be closed as fixed.
70326e2e-868d-4f8a-bfa5-12ef0400eae6 (request) and 77688256-3e9d-49be-9e1a-59da34714f72 (response), wired into 5 customer tenants, have empty function bodies. SCIM POSTs from Okta create users with no fields → FA's bean validation returns 400. Confirmed by reading the lambda bodies and reproducing successful SCIM POST against FA after replacing them with working per-tenant lambdas.scope FA's SCIM endpoint requires. Already addressed by MCPG-189 / PR #479. Out of scope for this umbrella.user.create.complete / user.update.complete webhooks. Route handlers at apps/admin/app/api/fusionauth/webhooks/user-created/route.ts and exist with full test coverage but the provisioning code at never registers them with FA. Every customer tenant is missing these subscriptions..../user-updated/route.tsapps/admin/server/fusionauth-provisioning-webhooks.ts:56-91eventConfiguration. Every customer tenant has eventConfiguration.events: {}. FA requires events explicitly enabled at the tenant level before any webhook fires, regardless of subscription. No webhook has ever fired for any customer tenant, not just SCIM ones — also affects user.deactivate, user.delete, all group events.apps/admin/app/api/fusionauth/webhooks/validation.ts and user-upsert-route.ts expect payload.user / payload.userId at the top level. FA actually nests them inside payload.event.user. Every real FA webhook delivery to our endpoint returns 400 invalid_webhook_payload. Same bug exists in the user-deactivated, user-deleted, and user-reactivated route handlers.Build the fixes as a stack of 5 PRs that land in order. The first 4 PRs change behavior for new orgs only; the 5th PR explicitly backfills existing orgs. This separation lets us validate the entire chain against a freshly-provisioned test org before touching any existing customer state.
fix(scim): accept FA webhook payload shape (event.user) — Receiver-side fix for Bug 5. Updates FusionAuthWebhookUserSchema and the upsert/deactivated/deleted/reactivated route handlers to read payload.event.user.id and payload.event.user.{email,active,...}. Pure code; no FA-side state. Production behavior unchanged on merge.feat(scim): create per-tenant working SCIM User lambdas during provisioning — Sender-side fix for Bug 1. Provisioning creates Composio {orgSlug} SCIM User {Request,Response} Converter lambdas with real bodies (mirroring the existing per-tenant Group lambda pattern). Sets user.data.source = 'scim' source-scope marker. Includes ensureScimUserLambdas(orgId) repair helper but does not invoke it on existing orgs.feat(scim): subscribe to user.create.complete + user.update.complete webhooks — Fix for Bug 3. Adds two entries to fusionauth-provisioning-webhooks.ts. Includes ensureScimUserWebhooks(orgId) repair helper.feat(scim): enable tenant eventConfiguration during provisioning — Fix for Bug 4. Sets eventConfiguration.events to enable the 13+ event types our webhooks subscribe to. Includes ensureScimEventConfiguration(orgId) repair helper.chore(scim): one-shot backfill for existing customer tenants — Standalone script at apps/admin/scripts/repair-scim-provisioning.ts. Calls each ensureScim* helper from PRs 2-4 for one or all SCIM-enabled orgs. Supports --org=<slug> and --all flags. Supports --dry-run showing exactly which tenants would change and what would change before committing. Idempotent. This is the "flip the switch for existing orgs" PR.After PRs 1-4 land in production:
scim_user row created, projection runs, user surfaces in SCIM Settings → Unmatched (or People page if rules match).--dry-run, then per-tenant for early customers, then --all.scim_unmatched_user even after all 5 bugs are fixed; that's the existing product behavior, not a bug.buildSamlIdentityProviderPayload setting createRegistration: true + linkingStrategy: 'LinkByEmail'. No code change needed.planktoncomposio tenant has the custom per-tenant group lambda with source-scope marker; other tenants use the FA Default. This is a nice-to-have hygiene cleanup but not correctness — group sync works today. Worth folding into PR 2 if straightforward; otherwise file separately.All five bugs confirmed against the planktoncomposio FA tenant (1ea93b19-2f09-4b28-a71e-470f3e25a2e9) via manual reproduction. Patch on Plankton verified end-to-end success (Okta task SUCCESS, user created in FA with correct fields, FA fired webhook, admin endpoint received it; Bug 5 was the final blocker preventing the ingestion). All session changes have been reverted; Plankton is back to its pre-session state.
--dry-run against all existing SCIM-enabled orgs; output reviewed.The latest updates on your projects. Learn more about Vercel for GitHub.
| Project | Deployment | Actions | Updated (UTC) |
|---|---|---|---|
| composio-enterprise-admin | May 20, 2026 5:45pm |
| Project | Deployment | Actions | Updated (UTC) |
|---|---|---|---|
| composio-enterprise-internal | May 20, 2026 5:45pm |
Someone is attempting to deploy this pull request to the Composio Team on Vercel.
No GitHub account was found matching the commit author email address.
To deploy this pull request, the commit author's email address needs to be associated with a GitHub account.
Learn more about how to change the commit author information.