Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
25 KiB
25 KiB
Scratchpad — MSP Tenant-First SSO Provider Resolution
- Plan slug:
2026-02-23-msp-tenant-first-sso-provider-resolution - Created:
2026-02-23
What This Is
Working notes for MSP SSO tenant-first resolver and provider-settings changes (Microsoft + Google), with CE enablement and no user-enumeration leakage.
Decisions
- (2026-02-23) Scope includes both Microsoft and Google for MSP SSO tenant-first resolution; client portal remains out of scope.
- (2026-02-23) Resolver behavior: tenant config first, app fallback second, generic failure when no source exists.
- (2026-02-23) Unknown-user attempts must not produce externally distinguishable behavior from known-user-missing-provider cases.
- (2026-02-23) Microsoft provider credentials will be managed in Providers settings, not per-provider email/calendar forms.
- (2026-02-23) CE MSP SSO will be enabled through shared auth codepath changes instead of EE-only UI gating.
- (2026-02-23) Resolver context will use short-lived signed cookie metadata (no raw secrets) to drive per-request secret selection.
- (2026-02-23) Keep implementation core-focused: no dedicated metrics/dashboard/rollout framework changes in this phase.
- (2026-02-23) Added a dedicated
MicrosoftIntegrationSettingsProviders card now, with action wiring deferred to F002-F011 to keep each checklist item atomic.
Discoveries / Constraints
- (2026-02-23) Providers setup currently shows only Google (
packages/integrations/src/components/settings/integrations/IntegrationsSettingsPage.tsx). - (2026-02-23) CE MSP SSO entry is a null stub (
packages/auth/src/components/SsoProviderButtons.tsx), while EE maps toee/server/src/components/auth/SsoProviderButtons.tsxviaserver/next.config.mjs. - (2026-02-23) NextAuth provider registration in shared auth options is currently EE-gated (
packages/auth/src/lib/nextAuthOptions.ts) and uses app OAuth keys. - (2026-02-23) NextAuth options are cached (
cachedOptions), which conflicts with per-request credential-source selection. - (2026-02-23) Secret provider interface supports tenant writes but not app writes (
packages/core/src/lib/secrets/ISecretProvider.ts), so Providers UI cannot write app-wide OAuth keys. - (2026-02-23) Microsoft integration flows already use tenant secret keys (
microsoft_client_id,microsoft_client_secret,microsoft_tenant_id) in several existing routes/actions. - (2026-02-23) Google provider settings already persist tenant
google_client_id/google_client_secretand can be reused as tenant SSO source for Google. - (2026-02-23) Existing calendar OAuth state store (
packages/integrations/src/utils/calendar/oauthStateStore.ts) demonstrates Redis + memory fallback pattern for short-lived one-time state. - (2026-02-23) Providers tab currently renders one "Google" integration entry that can host both provider cards in a single container (
IntegrationsSettingsPage.tsx).
Progress Log
- (2026-02-23)
F001complete: added Microsoft provider card component atpackages/integrations/src/components/settings/integrations/MicrosoftIntegrationSettings.tsxand rendered it in Providers tab beneath Google settings. - (2026-02-23)
T001complete: addedIntegrationsSettingsPage.providers.test.tsto assert Providers composition includes bothGoogleIntegrationSettingsandMicrosoftIntegrationSettings. - (2026-02-23)
F002complete: addedgetMicrosoftIntegrationStatusaction inpackages/integrations/src/actions/integrations/microsoftActions.tswith masked secret output, derived Microsoft redirect URIs (email,calendar,sso), and scope metadata. - (2026-02-23)
F003complete: addedsaveMicrosoftIntegrationSettingsaction with validation for required client ID/client secret and optional tenant ID normalization (commondefault). - (2026-02-23)
F004complete: addedresetMicrosoftProvidersToDisconnectedaction that disconnects Microsoft email/calendar providers and clears Microsoft token + webhook state acrossmicrosoft_email_provider_configandmicrosoft_calendar_provider_config. - (2026-02-23)
F005complete: exported Microsoft integrations actions from bothpackages/integrations/src/actions/integrations/index.tsandpackages/integrations/src/actions/index.ts. - (2026-02-23)
F006complete:saveMicrosoftIntegrationSettingspersistsmicrosoft_client_idusingsecretProvider.setTenantSecret(tenant, 'microsoft_client_id', clientId). - (2026-02-23)
F007complete:saveMicrosoftIntegrationSettingspersistsmicrosoft_client_secretas tenant secret. - (2026-02-23)
F008complete:saveMicrosoftIntegrationSettingspersistsmicrosoft_tenant_idwith defaultcommonwhen input is blank. - (2026-02-23)
F009complete: Microsoft provider settings UI now loads status and displays masked secret indicator (Stored secret: ••••) viastatus.config.clientSecretMasked. - (2026-02-23)
F010complete:saveMicrosoftIntegrationSettingsandresetMicrosoftProvidersToDisconnectednow enforce RBAC viahasPermission(user, 'system_settings', 'update'). - (2026-02-23)
F011complete: status/save/reset Microsoft actions consistently reject client-portal user context withForbidden. - (2026-02-23)
F012complete: addedgetMicrosoftProviderReadiness(tenant)helper inpackages/integrations/src/actions/integrations/providerReadiness.tsrequiring bothmicrosoft_client_idandmicrosoft_client_secret. - (2026-02-23)
F013complete: addedgetGoogleProviderReadiness(tenant)helper that checks onlygoogle_client_id+google_client_secret(no Gmail Pub/Sub dependency). - (2026-02-23)
F014complete: removed manualclientId/clientSecretrequirements and fields fromMicrosoftProviderFormschema/UI; OAuth configuration now relies on Providers-managed credentials. - (2026-02-23)
F015complete: Microsoft email form now shows a "Configure Providers first" CTA (configure-microsoft-providers-link) when Microsoft provider readiness is false. - (2026-02-23)
F016complete: Microsoft calendar form now checks provider readiness, shows a Providers-first CTA when missing, and disables OAuth connect until provider settings are ready. - (2026-02-23)
F017complete:persistMicrosoftConfignow resolves Microsoft credentials from tenant provider secrets before per-provider payload values, so CE email provider persistence does not require form-entered client credentials. - (2026-02-23)
F018complete: Microsoft calendar form persists provider metadata without client credential inputs by creating/updating providers with provider-settings-first OAuth flow. - (2026-02-23)
F019complete: replaced CESsoProviderButtonsnull stub with a real Google/Microsoft MSP SSO button component inpackages/auth/src/components/SsoProviderButtons.tsx. - (2026-02-23)
F020complete: MSP SSO buttons are disabled until a non-empty email is entered (hasEmailgate inSsoProviderButtons). - (2026-02-23)
F021complete: Microsoft SSO button now callsPOST /api/auth/msp/sso/resolvewith{ provider: 'azure-ad', email, callbackUrl }before invokingsignIn('azure-ad'). - (2026-02-23)
F022complete: Google SSO button now follows the same resolver-first flow (provider: 'google') beforesignIn('google'). - (2026-02-23)
F023complete: MSP login SSO UI now always shows the same generic start-failure message and does not surface resolver-specific error text. - (2026-02-23)
F024complete: client portal login remains unchanged;ClientLoginFormstill keeps SSO section commented out. - (2026-02-23)
F025complete: added unauthenticated resolver routeserver/src/app/api/auth/msp/sso/resolve/route.tsand shared resolver utilities inpackages/auth/src/lib/sso/mspSsoResolution.ts. - (2026-02-23)
F026complete: resolver validates provider/email/callbackUrl, normalizes email casing/whitespace, and returns only generic failure responses for malformed input. - (2026-02-23)
F027complete: resolver performs internal-user lookup on normalized email (LOWER(email)) strictly for source-selection decisions. - (2026-02-23)
F028complete: resolver selects tenant source when an internal user exists and tenant credentials for the chosen provider are ready. - (2026-02-23)
F029complete: resolver falls back to app OAuth credentials when tenant source is unavailable and provider fallback keys are configured. - (2026-02-23)
F030complete: unknown-user attempts follow the same external success/failure behavior as known-user-without-tenant-config paths. - (2026-02-23)
F031complete: resolver returns stable200+{ ok: true|false }schema regardless of lookup outcome, with generic failure payload shape. - (2026-02-23)
F032complete: resolver issues signed, short-lived, httpOnlymsp_sso_resolutioncookie containing only source metadata. - (2026-02-23)
F033complete: resolver cookie payload intentionally omits raw OAuth client IDs and client secrets. - (2026-02-23)
F034complete: Microsoft fallback readiness in resolver usesMICROSOFT_OAUTH_CLIENT_ID+MICROSOFT_OAUTH_CLIENT_SECRET(env/app secrets). - (2026-02-23)
F035complete: Google fallback readiness in resolver usesGOOGLE_OAUTH_CLIENT_ID+GOOGLE_OAUTH_CLIENT_SECRET(env/app secrets). - (2026-02-23)
F036complete: resolver returns the genericok:falsefailure payload when no tenant or app credential source is available. - (2026-02-23)
F037complete: resolver now applies in-memory rate limiting keyed by request IP + hashed normalized email bucket. - (2026-02-23)
F038complete: resolver logs now include only provider/source classification and generic failure context without raw email, secrets, or explicit existence flags. - (2026-02-23)
F039complete: removed EE-only gating around Google/Microsoft provider registration in NextAuth options so CE can register MSP OAuth providers when credentials exist. - (2026-02-23)
F040complete: removed staticcachedOptions;getAuthOptions()now rebuilds per request so resolver cookie context can affect provider credentials. - (2026-02-23)
F041complete: OAuth secret resolution now readsmsp_sso_resolutioncookie context and applies tenant-scoped Google/Microsoft credentials when valid tenant source is requested. - (2026-02-23)
F042complete: when resolver cookie context is missing/invalid/expired, OAuth secret resolution keeps using app-level fallback credentials only. - (2026-02-23)
F043complete: tenant-source cookie context is accepted only after HMAC signature and expiry checks inparseAndVerifyMspSsoResolutionCookie. - (2026-02-23)
F044complete: resolver writes a freshly signed cookie (new nonce + expiry) on each successful start attempt, replacing stale context. - (2026-02-23)
F045complete: added CE-safe OAuth mappermapCeOAuthProfileToExtendedUserfor Google/Microsoft MSP sign-in lookups by normalized internal email. - (2026-02-23)
F046complete: Google/Microsoft profile callbacks now route throughmapOAuthProfileToExtendedUser, which selects CE mapper in community edition. - (2026-02-23)
F047complete: enterprise builds still follow the existing SSO registry mapper path (isEnterprisebranch) unchanged. - (2026-02-23)
F048complete: CE now bypasses EE account-link persistence by short-circuitingensureOAuthAccountLinkwhenisEnterpriseis false. - (2026-02-23)
F049complete: Microsoft provider issuer now uses${tenantId || 'common'}to ensure empty tenant IDs default tocommon. - (2026-02-23)
F050complete: added explicit anti-enumeration comments in resolver route to prevent exposing lookup outcomes in client-visible responses. - (2026-02-23)
F051complete:.env.examplenow documentsGOOGLE_OAUTH_*/MICROSOFT_OAUTH_*as CE MSP SSO fallback keys (not EE-only). - (2026-02-23)
F052complete: addeddocs/integrations/provider-setup-order.mddocumenting Providers-first setup, then integration-level OAuth connection for Google/Microsoft.
Commands / Runbooks
- (2026-02-23) List existing plans and artifacts:
find ee/docs/plans -maxdepth 2 -type f \( -name PRD.md -o -name features.json -o -name tests.json -o -name SCRATCHPAD.md \) | head -n 40
- (2026-02-23) Scaffold this plan folder from ALGA templates:
python3 /Users/roberisaacs/.codex/skills/alga-plan/scripts/scaffold_plan.py "MSP Tenant-First SSO Provider Resolution" --slug 2026-02-23-msp-tenant-first-sso-provider-resolution --no-date-prefix
- (2026-02-23) Validate plan artifact structure:
python3 /Users/roberisaacs/.codex/skills/alga-plan/scripts/validate_plan.py --plan-dir ee/docs/plans/2026-02-23-msp-tenant-first-sso-provider-resolution
Links / References
- Existing Google provider settings PRD template pattern:
ee/docs/plans/2026-01-04-tenant-owned-google-oauth/PRD.md
- Shared auth options and provider gating:
packages/auth/src/lib/nextAuthOptions.ts
- CE/EE SSO button entry aliasing:
server/next.config.mjspackages/auth/src/components/SsoProviderButtons.tsxee/server/src/components/auth/SsoProviderButtons.tsx
- Providers settings page:
packages/integrations/src/components/settings/integrations/IntegrationsSettingsPage.tsx
- Microsoft email/calendar forms (CE):
packages/integrations/src/components/email/MicrosoftProviderForm.tsxpackages/integrations/src/components/calendar/MicrosoftCalendarProviderForm.tsx
- Secret provider interface:
packages/core/src/lib/secrets/ISecretProvider.ts
Open Questions
- None blocking for initial implementation phase.
- (2026-02-23)
T002complete: added unit coverage inmicrosoftActions.test.tsprovinggetMicrosoftIntegrationStatusreturnssuccess:truefor authorized internal admin context. - (2026-02-23)
T003complete:microsoftActions.test.tsasserts Microsoft status returns masked secret indicators and never returns raw client secret text. - (2026-02-23)
T004complete: unit coverage verifiessaveMicrosoftIntegrationSettingsrejects blankclientId. - (2026-02-23)
T005complete: unit coverage verifiessaveMicrosoftIntegrationSettingsrejects blankclientSecret. - (2026-02-23)
T006complete: save action test verifies defaultmicrosoft_tenant_idofcommonwhen tenant ID input is omitted. - (2026-02-23)
T007complete: save action test verifies persistence of tenant secret keymicrosoft_client_id. - (2026-02-23)
T008complete: save action test verifies persistence of tenant secret keymicrosoft_client_secret. - (2026-02-23)
T009complete: save action test verifies persistence of tenant secret keymicrosoft_tenant_id. - (2026-02-23)
T010complete: status action test validates derived redirect URIs and scope metadata for Microsoft email/calendar/SSO. - (2026-02-23)
T011complete: reset action test verifies Microsoft email provider rows are set disconnected and token/webhook fields are cleared. - (2026-02-23)
T012complete: reset action test verifies Microsoft calendar provider rows are set disconnected and token/subscription fields are cleared. - (2026-02-23)
T013complete: export coverage verifies Microsoft integration actions are present in integrations index entrypoints. - (2026-02-23)
T014complete: save action test verifies non-admin users withoutsystem_settings:updatereceiveForbidden. - (2026-02-23)
T015complete: status/save/reset action tests verify client-portal user context is denied withForbidden. - (2026-02-23)
T016/T017/T023implemented inproviderReadiness.test.ts; readiness now validated as secret-pair checks (microsoft_client_*,google_client_*) with explicit assertion that Google readiness does not depend on Gmail Pub/Sub keys. - (2026-02-23) Command run:
cd server && npx vitest run ../packages/integrations/src/actions/integrations/microsoftActions.test.ts ../packages/integrations/src/actions/integrations/providerReadiness.test.ts. - (2026-02-23)
T017complete:providerReadiness.test.tsverifies Google readiness is true only when bothgoogle_client_idandgoogle_client_secretare configured. - (2026-02-23)
T023complete: Google readiness coverage explicitly asserts Pub/Sub keys are not required for MSP SSO readiness decisions. - (2026-02-23)
T018complete:microsoftProviders.providersFirst.test.tsverifies CE Microsoft email form no longer requires manualclientId/clientSecretfields and uses providers-managed credentials. - (2026-02-23)
T019complete: providers-first contract test verifies Microsoft email form renders CTA (configure-microsoft-providers-link) to Providers settings when readiness is false. - (2026-02-23)
T020complete: providers-first contract test verifies Microsoft calendar form renders CTA (configure-microsoft-calendar-providers-link) when provider readiness is missing. - (2026-02-23)
T021complete: calendar providers-first contract test verifies create flow submits metadata and uses empty vendor credential fields (no manual OAuth credential entry requirement). - (2026-02-23)
T022complete: persistence contract test verifies Microsoft email provider action derives effective credentials from hosted/tenant secrets and does not rely on form-entered secrets. - (2026-02-23)
T024complete: addedSsoProviderButtons.msp.test.tsxto validate CE MSP login renders both Google and Microsoft SSO buttons. - (2026-02-23) Command run:
cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/components/SsoProviderButtons.msp.test.tsx ../packages/auth/src/components/ClientLoginForm.ssoGuard.test.ts. - (2026-02-23)
T025complete: SSO button interaction tests verify both providers stay disabled until a non-empty email is supplied. - (2026-02-23)
T026complete: component test verifies Microsoft button performs resolver POST first and only then invokessignIn('azure-ad'). - (2026-02-23)
T027complete: component test verifies Google button performs resolver POST first and then callssignIn('google'). - (2026-02-23)
T028complete: failure-path component test verifies resolver/network failures always emit one generic MSP SSO start error message. - (2026-02-23)
T029complete: client portal login contract test verifiesClientLoginFormkeeps SSO section commented/disabled with no new client portal SSO affordance. - (2026-02-23)
T030complete: added resolver route unit coverage validating valid payload ->{ ok: true }and signedmsp_sso_resolutioncookie set on success. - (2026-02-23) Added auth/server test suites:
packages/auth/src/lib/sso/mspSsoResolution.test.tsandserver/src/app/api/auth/msp/sso/resolve/route.test.ts. - (2026-02-23) Added Vitest alias for
@alga-psa/auth/lib/sso/mspSsoResolutioninserver/vitest.config.tsto enable route test resolution. - (2026-02-23) Command run:
cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts src/app/api/auth/msp/sso/resolve/route.test.ts. - (2026-02-23)
T031complete: resolver route test verifies invalid provider input returns the generic{ ok:false, message }response contract. - (2026-02-23)
T032complete:mspSsoResolution.test.tsverifies resolver lowercases/trims email before DB lookup binding. - (2026-02-23)
T033complete: helper test verifies Microsoft tenant source selection when user exists and tenant Microsoft secrets are ready. - (2026-02-23)
T034complete: helper test verifies Google tenant source selection when user exists and tenant Google secrets are ready. - (2026-02-23)
T035complete: helper test verifies Microsoft app fallback source when tenant Microsoft secrets are unavailable. - (2026-02-23)
T036complete: helper test verifies Google app fallback source when tenant Google secrets are unavailable. - (2026-02-23)
T037complete: route test verifies unknown-user and known-user-missing-tenant both produce identical success schema with app fallback. - (2026-02-23)
T038complete: route test verifies unknown-user and known-user-no-source both return identical generic failure payload. - (2026-02-23)
T039complete: signed-cookie helper test verifies payload/value exclude raw OAuth client IDs and secrets. - (2026-02-23)
T040complete: signed-cookie helper test validates provider/source/issuedAt/expiresAt/nonce fields plus parseable signature. - (2026-02-23)
T041complete: helper test asserts Microsoft app fallback checks useMICROSOFT_OAUTH_CLIENT_IDandMICROSOFT_OAUTH_CLIENT_SECRET. - (2026-02-23)
T042complete: helper test asserts Google app fallback checks useGOOGLE_OAUTH_CLIENT_IDandGOOGLE_OAUTH_CLIENT_SECRET. - (2026-02-23)
T043complete: helper test verifies invalid signature and expired cookie contexts are rejected by resolver-cookie parser. - (2026-02-23)
T044complete: route test verifies rate-limited requests still return the same generic failure response. - (2026-02-23)
T045complete: route test verifies logs include provider/source classification without raw email, secret material, or user-existence fields. - (2026-02-23)
T046complete: addednextAuthOptions.mspContract.test.tsasserting CE path registers Google/Microsoft providers when credential inputs are available. - (2026-02-23) Added auth/doc test suites:
ceOAuthProfileMapper.test.ts,nextAuthOptions.mspContract.test.ts, andmspSsoDocsContract.test.ts. - (2026-02-23) Command run:
cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/ceOAuthProfileMapper.test.ts ../packages/auth/src/lib/nextAuthOptions.mspContract.test.ts ../packages/auth/src/lib/sso/mspSsoDocsContract.test.ts. - (2026-02-23)
T047complete: NextAuth contract test verifiesgetAuthOptionsreturnsbuildAuthOptions()directly and no staticcachedOptionscache remains. - (2026-02-23)
T048complete: NextAuth contract test verifies tenant-scoped Microsoft credentials are read when resolver cookie selects tenant source. - (2026-02-23)
T049complete: NextAuth contract test verifies tenant-scoped Google credentials are read when resolver cookie selects tenant source. - (2026-02-23)
T050complete: NextAuth contract test verifies invalid/absent resolver context returns early to app-level fallback credential set. - (2026-02-23)
T051complete: NextAuth contract test verifies expired resolver context is ignored through the same early-return fallback path. - (2026-02-23)
T052complete: resolver route test verifies consecutive successful starts set different cookie values (overwrite behavior). - (2026-02-23)
T053complete: CE mapper unit test verifies normalized-email resolution for Microsoft profile and expected extended user shape. - (2026-02-23)
T054complete: CE mapper unit test verifies normalized-email resolution for Google profile and expected extended user shape. - (2026-02-23)
T055complete: CE mapper unit test verifies inactive accounts are rejected for MSP OAuth sign-in. - (2026-02-23)
T056complete: CE mapper unit test verifies non-internal/client user types are rejected for MSP OAuth sign-in. - (2026-02-23)
T057complete: NextAuth contract test verifies enterprise path still delegates profile mapping to EE SSO registry implementation. - (2026-02-23)
T058complete: NextAuth contract test verifiesensureOAuthAccountLinkshort-circuits whenisEnterpriseis false. - (2026-02-23)
T059complete: NextAuth contract test verifies Microsoft issuer uses tenant ID withcommondefault in dynamic and sync provider configuration. - (2026-02-23)
T060complete: docs contract test verifies explicit anti-enumeration guidance comments remain in resolver route implementation. - (2026-02-23)
T061complete: docs contract test verifies.env.exampleincludes CE MSP SSO fallback usage forGOOGLE_OAUTH_*andMICROSOFT_OAUTH_*. - (2026-02-23)
T062complete: docs contract test verifies provider setup order documentation instructs Providers settings before integration OAuth connections. - (2026-02-23)
T063complete: resolver helper integration-style test covers tenant-source selection when a matching internal user row and tenant provider secrets are present. - (2026-02-23)
T064complete: resolver route test covers unknown-email guard path returning generic response without user-existence disclosure. - (2026-02-23)
T065complete: resolver helper integration-style test covers app-source selection when user row exists but tenant provider readiness is absent. - (2026-02-23)
T066complete: expandedSsoProviderButtons.msp.test.tsxwith end-to-end contract scenario for Microsoft tenant-source success from login button click through NextAuthsignIninvocation. - (2026-02-23) Updated auth flow contract tests:
SsoProviderButtons.msp.test.tsx,ClientLoginForm.ssoGuard.test.ts, andMspCredentialsFlow.contract.test.ts. - (2026-02-23) Command run:
cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/components/SsoProviderButtons.msp.test.tsx ../packages/auth/src/components/ClientLoginForm.ssoGuard.test.ts ../packages/auth/src/components/MspCredentialsFlow.contract.test.ts. - (2026-02-23)
T067complete: SSO component end-to-end contract scenario verifies Google tenant-source success path reaches NextAuthsignIn. - (2026-02-23)
T068complete: SSO component end-to-end contract scenario verifies Microsoft app-fallback success path reaches NextAuthsignIn. - (2026-02-23)
T069complete: SSO component end-to-end contract scenario verifies Google app-fallback success path reaches NextAuthsignIn. - (2026-02-23)
T070complete: end-to-end contract scenario verifies unknown-user and known-unconfigured tenant failures surface the identical generic UI message. - (2026-02-23)
T071complete: credentials-flow contract test verifies MSP credentials sign-in path remains separate from resolver-cookie handling. - (2026-02-23)
T072complete: client portal login contract test verifies SSO affordances remain disabled/commented for end-to-end client portal flow.