Hermes 284313f908
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
Initial import of AlgaPSA codebase from PSA server
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz

Source: /opt/alga-psa on psa.joliet.tech
2026-06-22 16:12:17 -05:00

34 KiB

Scratchpad — EE+CE Domain-Scoped SSO Takeover and Domain Approval

  • Plan slug: ee-ce-domain-scoped-sso-takeover
  • Created: 2026-03-03

What This Is

Working notes for expanding domain-scoped MSP SSO discovery to support:

  • EE domain ownership approval before tenant takeover
  • CE advisory domain registration behavior
  • reliable Nine Minds app-level fallback for unmanaged domains

Decisions

  • (2026-03-03) CE domain registration is advisory (no mandatory ownership verification gate).
  • (2026-03-03) EE requires domain ownership verification before a tenant can take over SSO routing for a domain.
  • (2026-03-03) Unmanaged/unapproved domains should route to Nine Minds app-level SSO providers.
  • (2026-03-03) Keep /auth/msp/signin UX and anti-enumeration response contracts intact.
  • (2026-03-03) Lifecycle status model for MSP SSO domain claims uses advisory | pending | verified | verified_legacy | rejected | revoked with per-status timestamps to preserve backward compatibility while enabling EE verification workflows.
  • (2026-03-03) Verification challenges are stored as tenant-scoped records keyed to domain claim rows so challenge rotation can invalidate prior material while preserving audit timestamps.
  • (2026-03-03) Lifecycle backfill uses deployment edition context (EDITION / NEXT_PUBLIC_EDITION) because MSP tenant rows do not carry per-tenant CE/EE markers in the shared schema.
  • (2026-03-03) Shared helpers for domain lifecycle now live in packages/auth/src/lib/sso/mspSsoResolution.ts so both discovery and settings actions use the same normalization and validation behavior.
  • (2026-03-03) Added listMspSsoDomainClaims action with permission gate parity to existing domain management checks; action returns lifecycle metadata for each active claim.
  • (2026-03-03) Added requestMspSsoDomainClaim action to create/reuse pending claims and provision DNS TXT challenge material with hashed verification values.
  • (2026-03-03) Added refreshMspSsoDomainClaimChallenge action that always rotates active challenge material for an existing claim and reasserts pending claim status.
  • (2026-03-03) Added verifyMspSsoDomainClaimOwnership action that resolves DNS TXT records for the stored challenge label/value and promotes claim status to verified only on exact match.
  • (2026-03-03) Added revokeMspSsoDomainClaim action to transition active claims to revoked and invalidate any still-active verification challenges.
  • (2026-03-03) CE advisory save/remove path now explicitly sets/retains claim_status='advisory' on active registrations without any ownership proof gate.
  • (2026-03-03) Verified ownership conflict guard is now enforced twice: app-layer check during verify action and DB-layer partial unique index on lower(domain) for active verified|verified_legacy rows.
  • (2026-03-03) EE settings UI now renders lifecycle-aware claim rows with status badges and per-claim actions (request, verify, refresh challenge, revoke) instead of only a plain editable domain list.
  • (2026-03-03) Pending EE claims now render inline DNS TXT instructions in settings (host + value) sourced from the active challenge row.
  • (2026-03-03) CE UI copy now explicitly labels domain registration as advisory and clarifies that ownership verification is not enforced in Community Edition.
  • (2026-03-03) Settings copy now consistently states fallback behavior: domains without eligible claims route to Nine Minds app-level SSO providers.
  • (2026-03-03) Discovery helper now resolves domain ownership with both edition and claim lifecycle context (eligibleForTakeover) before selecting tenant vs app source.
  • (2026-03-03) EE routing gate is now strict: only verified/verified_legacy claims can produce tenant-scoped provider discovery; all other statuses bypass tenant takeover.
  • (2026-03-03) EE fallback behavior now explicitly routes pending, rejected, revoked, and ambiguous domain claims to app-level provider discovery.
  • (2026-03-03) CE routing now treats advisory claims as takeover-eligible, enabling tenant-scoped provider discovery without ownership verification requirements.
  • (2026-03-03) Unregistered/unresolved domains in both editions now consistently return app-level discovery output, preserving fallback behavior independent of tenant claim state.
  • (2026-03-03) Discover route contract remains invariant ({ ok: true, providers: [] } on invalid/rate-limited/error paths) even after lifecycle-aware helper changes.

Discoveries / Constraints

  • (2026-03-03) Existing domain-scoped discovery/resolver path already exists at server/src/app/api/auth/msp/sso/discover/route.ts and server/src/app/api/auth/msp/sso/resolve/route.ts.
  • (2026-03-03) Current domain mapping persistence uses msp_sso_tenant_login_domains and already supports normalized domain lookup.
  • (2026-03-03) Current fallback behavior already supports app-level provider readiness (GOOGLE_OAUTH_*, MICROSOFT_OAUTH_*).
  • (2026-03-03) CE/EE login wiring currently relies on edition aliasing for SSO provider buttons; CE parity must explicitly keep discovery-enabled behavior.
  • (2026-03-03) Existing managed email-domain flow (Resend-style) provides a useful pattern for async domain verification lifecycle in EE settings.
  • (2026-03-03) Existing msp_sso_tenant_login_domains table is already deployed in this branch and uses only is_active; lifecycle behavior must be introduced as additive columns to avoid breaking current discovery.
  • (2026-03-03) There is no tenant-level CE/EE column in the database schema; edition-aware defaults/backfill must rely on deployment edition context (env) rather than per-tenant data.
  • (2026-03-03) Challenge persistence needs composite tenant+claim foreign key (tenant, claim_id) because login-domain claims use composite primary key (tenant, id) for Citus compatibility.
  • (2026-03-03) Backfill migration sets EE existing rows to verified_legacy with inferred claimed_at/verified_at timestamps, while CE keeps advisory defaults.
  • (2026-03-03) Domain normalization now strips common decorations (@, mailto:, URL host wrappers, trailing dot) before validation, reducing mismatch drift between settings and login discovery.
  • (2026-03-03) Claims listing tolerates rollout ordering by checking lifecycle column existence at runtime and defaulting unknown/missing statuses to advisory.
  • (2026-03-03) Claim request action is idempotent for existing same-tenant pending claims when an active challenge already exists; otherwise it rotates by deactivating old active challenges and creating a new one.
  • (2026-03-03) Refresh semantics are intentionally non-idempotent: each refresh deactivates previous active challenge rows and creates a new DNS TXT value for the same claim id.
  • (2026-03-03) Verification action keeps neutral admin-safe failure messaging for DNS mismatch/missing challenge and does not expose sensitive internals.
  • (2026-03-03) Revoke flow updates lifecycle metadata (claim_status_updated_at, revoked_at) and keeps the claim row for historical/audit purposes instead of deleting it.
  • (2026-03-03) CE advisory remove remains non-destructive (is_active=false) so historical rows stay available for later reactivation/audit.
  • (2026-03-03) Conflict is resolved at verify time (not request time), matching PRD recommendation and preserving neutral request behavior.
  • (2026-03-03) CE and EE UX now branch in the same component using edition detection: CE keeps advisory save/remove list; EE uses immediate claim workflow actions.
  • (2026-03-03) Verification status feedback is surfaced through inline/error alert state and action-specific toasts (verify/refresh/request/revoke outcomes).
  • (2026-03-03) Header/description messaging now diverges by edition so EE focuses on claim lifecycle actions while CE emphasizes advisory registration semantics.
  • (2026-03-03) Added a persistent informational alert in the settings panel to reinforce fallback behavior independently of edition-specific controls.
  • (2026-03-03) Claim status precedence normalization (verified > verified_legacy > pending > advisory > rejected > revoked) prevents duplicate-row drift from producing unstable routing decisions.
  • (2026-03-03) Ambiguous multi-tenant mappings remain fail-closed and are never eligible for EE tenant takeover.
  • (2026-03-03) EE non-eligible statuses preserve anti-enumerating behavior by returning normal app-source provider readiness (including empty set when app providers are not configured).
  • (2026-03-03) CE still blocks revoked/rejected claims from tenant routing, preventing stale/deactivated claims from taking over discovery.
  • (2026-03-03) Discovery still returns valid neutral payloads when fallback providers are empty, avoiding auth-flow branching on domain existence.
  • (2026-03-03) Discovery logs remain safe metadata only (source, providerCount, domain, ambiguous), with no raw email disclosure.

Commands / Runbooks

  • (2026-03-03) Scaffolded plan bundle:
    • python3 /Users/roberisaacs/.codex/skills/alga-plan/scripts/scaffold_plan.py "EE+CE Domain-Scoped SSO Takeover and Domain Approval" --slug ee-ce-domain-scoped-sso-takeover
  • (2026-03-03) Optional plan validation:
    • python3 /Users/roberisaacs/.codex/skills/alga-plan/scripts/validate_plan.py ee/docs/plans/2026-03-03-ee-ce-domain-scoped-sso-takeover
  • (2026-03-03) F001 implementation checks:
    • node -c server/migrations/20260303100000_add_msp_sso_domain_claim_lifecycle.cjs
    • npx vitest run server/src/test/unit/migrations/mspSsoTenantLoginDomainsMigration.test.ts
  • (2026-03-03) F002 implementation checks:
    • node -c server/migrations/20260303101000_create_msp_sso_domain_verification_challenges.cjs
    • cd server && npx vitest run src/test/unit/migrations/mspSsoTenantLoginDomainsMigration.test.ts
  • (2026-03-03) F003 implementation checks:
    • node -c server/migrations/20260303102000_backfill_msp_sso_domain_claim_status_defaults.cjs
    • cd server && npx vitest run src/test/unit/migrations/mspSsoTenantLoginDomainsMigration.test.ts
  • (2026-03-03) F004 implementation checks:
    • cd server && npx vitest run ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
    • cd server && npx vitest run ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
  • (2026-03-03) F005 implementation checks:
    • cd server && npx vitest run ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
  • (2026-03-03) F006 implementation checks:
    • cd server && npx vitest run ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
  • (2026-03-03) F007 implementation checks:
    • cd server && npx vitest run ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
  • (2026-03-03) F008 implementation checks:
    • cd server && npx vitest run ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
  • (2026-03-03) F009 implementation checks:
    • cd server && npx vitest run ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
  • (2026-03-03) F010 implementation checks:
    • cd server && npx vitest run ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
  • (2026-03-03) F011 implementation checks:
    • node -c server/migrations/20260303103000_enforce_verified_msp_sso_domain_ownership.cjs
    • cd server && npx vitest run ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
  • (2026-03-03) F012 implementation checks:
    • cd server && npx vitest run ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
    • cd server && npx vitest run ../packages/integrations/src/components/settings/integrations/IntegrationsSettingsPage.providers.test.ts
  • (2026-03-03) F013 implementation checks:
    • cd server && npx vitest run ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
    • cd server && npx vitest run ../packages/integrations/src/components/settings/integrations/IntegrationsSettingsPage.providers.test.ts
  • (2026-03-03) F014 implementation checks:
    • cd server && npx vitest run ../packages/integrations/src/components/settings/integrations/IntegrationsSettingsPage.providers.test.ts
  • (2026-03-03) F015 implementation checks:
    • cd server && npx vitest run ../packages/integrations/src/components/settings/integrations/IntegrationsSettingsPage.providers.test.ts
  • (2026-03-03) F016 implementation checks:
    • cd server && npx vitest run ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) F017 implementation checks:
    • cd server && npx vitest run ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) F018 implementation checks:
    • cd server && npx vitest run ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) F019 implementation checks:
    • cd server && npx vitest run ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) F020 implementation checks:
    • cd server && npx vitest run ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) F021 implementation checks:
    • cd server && npx vitest run src/app/api/auth/msp/sso/discover/route.test.ts
  • Prior domain-scoped discovery plan:
    • ee/docs/plans/2026-02-24-msp-domain-scoped-sso-discovery/PRD.md
  • Discovery/resolver implementation:
    • packages/auth/src/lib/sso/mspSsoResolution.ts
    • server/src/app/api/auth/msp/sso/discover/route.ts
    • server/src/app/api/auth/msp/sso/resolve/route.ts
  • Domain management actions/UI:
    • packages/integrations/src/actions/integrations/mspSsoDomainActions.ts
    • packages/integrations/src/components/settings/integrations/MspSsoLoginDomainsSettings.tsx
  • Managed email-domain reference patterns:
    • ee/server/src/lib/actions/email-actions/managedDomainActions.ts
    • packages/integrations/src/actions/email-actions/emailDomainActions.ts

Open Questions

  • Should EE verified-domain conflicts be blocked immediately at claim request time or at verification completion time?
  • Should EE verified claims support periodic re-verification in a future phase, or remain manual revoke/re-verify only?
  • (2026-03-03) Completed F022: resolver now revalidates tenant takeover eligibility at resolve-time using current domain lifecycle (resolveTenantForMspSsoDomain) before allowing tenant source, and safely falls back to app source only when allow-list permits and app credentials exist.
  • (2026-03-03) Security hardening tied to resolver revalidation: discovery cookie now carries normalized domain, and tenant discovery context is only used when resolver email domain matches cookie domain.
  • (2026-03-03) Validation run for F022:
    • cd server && npx vitest run ../packages/auth/src/lib/sso/mspSsoResolution.test.ts src/app/api/auth/msp/sso/discover/route.test.ts src/app/api/auth/msp/sso/resolve/route.test.ts
  • (2026-03-03) Completed F023: resolver generic failure contract remains invariant for invalid/disallowed/rate-limited resolution paths while lifecycle checks are applied internally.
  • (2026-03-03) Validation run for F023:
    • cd server && npx vitest run src/app/api/auth/msp/sso/resolve/route.test.ts
  • (2026-03-03) Completed F024: discovery payload now includes normalized domain and parsing rejects signed payloads with invalid domain values; resolve/discover cookie tests assert httpOnly/sameSite=lax/short TTL (maxAge=300).
  • (2026-03-03) Validation run for F024:
    • cd server && npx vitest run ../packages/auth/src/lib/sso/mspSsoResolution.test.ts src/app/api/auth/msp/sso/discover/route.test.ts src/app/api/auth/msp/sso/resolve/route.test.ts
  • (2026-03-03) Completed F025: MSP credentials sign-in path remains unchanged and isolated from resolver-cookie logic (MspCredentialsFlow.contract.test.ts).
  • (2026-03-03) Validation run for F025:
    • cd server && npx vitest run ../packages/auth/src/components/MspCredentialsFlow.contract.test.ts
  • (2026-03-03) Completed F026: added explicit client-portal auth contract coverage to assert no MSP SSO discovery/resolve endpoint wiring in client-portal sign-in code paths.
  • (2026-03-03) Note: src/test/unit/app/auth/client-portal/signin/page.test.ts currently fails in isolation due an existing import/mocking path mismatch (@alga-psa/db/models/UserSession), so validation used package-level contract tests instead.
  • (2026-03-03) Validation run for F026:
    • cd server && npx vitest run ../packages/auth/src/components/ClientLoginForm.ssoGuard.test.ts ../packages/auth/src/components/ClientPortalAuthUnchanged.contract.test.ts
  • (2026-03-03) Completed F027: CE/EE parity contract confirms MSP SSO entry wiring uses discovery-enabled provider buttons implementation (no null/stub path).
  • (2026-03-03) Validation run for F027:
    • cd server && npx vitest run ../packages/auth/src/components/ssoProviderButtonsImport.test.ts ../packages/auth/src/components/ssoProviderButtons.ceEeParity.test.ts
  • (2026-03-03) Completed F028: added contract assertion that MspLoginForm passes the live typed email state into SsoProviderButtons (email={email}), preserving discovery input propagation for CE/EE builds via shared entry wiring.
  • (2026-03-03) Validation run for F028:
    • cd server && npx vitest run ../packages/auth/src/components/ssoProviderButtonsImport.test.ts
  • (2026-03-03) Completed F029: existing MSP SSO button behavior suite continues to validate disabled state rules, in-flight discovery behavior, provider eligibility gating, disabled-click no-op, and remembered provider preference handling.
  • (2026-03-03) Validation run for F029:
    • cd server && npx vitest run ../packages/auth/src/components/SsoProviderButtons.msp.test.tsx
  • (2026-03-03) Completed F030: added tenant-admin runbook doc for EE domain takeover lifecycle (request -> DNS TXT verification -> verified -> revoke) at docs/integrations/msp-sso-domain-claims.md.
  • (2026-03-03) Validation run for F030:
    • cd server && npx vitest run ../packages/auth/src/lib/sso/mspSsoDocsContract.test.ts
  • (2026-03-03) Completed F031: documentation now includes CE advisory mode behavior, explicitly stating non-blocking ownership verification and advisory routing limitations.
  • (2026-03-03) Validation source: docs/integrations/msp-sso-domain-claims.md (section CE Advisory Domain Registration) and docs contract assertions.
  • (2026-03-03) Completed F032: documentation now includes Nine Minds app-level fallback prerequisites and unmanaged/unapproved domain routing behavior with required *_OAUTH_* env vars.
  • (2026-03-03) Validation source: docs/integrations/msp-sso-domain-claims.md (section App-Level Fallback) and docs contract assertions.
  • (2026-03-03) Completed F033: expanded action-level unit coverage for lifecycle endpoints and permission guards in mspSsoDomainActions.test.ts (forbidden checks across request/refresh/verify/revoke plus validation contracts).
  • (2026-03-03) Validation run for F033:
    • cd server && npx vitest run ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
  • (2026-03-03) Completed F034: expanded discovery/resolver matrix coverage with explicit EE verified/pending/revoked/ambiguous cases and CE advisory routing case in mspSsoResolution.test.ts, plus endpoint contract suites for discover/resolve.
  • (2026-03-03) Validation run for F034:
    • cd server && npx vitest run ../packages/auth/src/lib/sso/mspSsoResolution.test.ts src/app/api/auth/msp/sso/discover/route.test.ts src/app/api/auth/msp/sso/resolve/route.test.ts
  • (2026-03-03) Completed F035: route contract tests verify /auth/msp/signin entry path and callbackUrl passthrough/default behavior remain unchanged under lifecycle integration.
  • (2026-03-03) Validation run for F035:
    • cd server && npx vitest run ../packages/auth/src/components/MspSignInRoute.contract.test.ts
  • (2026-03-03) Completed T001: added migration contract suite server/src/test/unit/migrations/mspSsoDomainLifecycle.migrations.test.ts validating lifecycle schema additions (claim_status + lifecycle metadata columns/check constraint).
  • (2026-03-03) Validation run for T001:
    • cd server && npx vitest run src/test/unit/migrations/mspSsoDomainLifecycle.migrations.test.ts
  • (2026-03-03) Completed T002: migration contract suite covers challenge table creation/index contract in mspSsoDomainLifecycle.migrations.test.ts.
  • (2026-03-03) Completed T003: migration contract suite verifies rollback drops lifecycle columns and challenge table.
  • (2026-03-03) Completed T004: migration contract suite verifies EE backfill SQL sets verified_legacy defaults.
  • (2026-03-03) Completed T005: migration contract suite verifies CE backfill SQL sets advisory defaults.
  • (2026-03-03) Completed T006: domain normalization covered by helper normalization tests and save-domain normalization behavior.
  • (2026-03-03) Completed T007: malformed domain validation covered by deterministic neutral error assertions in action tests.
  • (2026-03-03) Completed T008: permission denial for list-claims and lifecycle actions covered in mspSsoDomainActions.test.ts.
  • (2026-03-03) Completed T009: claims list metadata contract covered in mspSsoDomainActions.test.ts (normalized claim fields + lifecycle timestamps).
  • (2026-03-03) Completed T010: request-claim happy path coverage added (pending claim + active DNS challenge creation).
  • (2026-03-03) Completed T011: request-claim idempotency coverage added for existing pending claim + active challenge.
  • (2026-03-03) Completed T012: refresh challenge coverage added for token rotation and invalidation of previous active challenge.
  • (2026-03-03) Completed T013: verify-claim success coverage added for matching DNS TXT challenge promoting claim to verified.
  • (2026-03-03) Completed T014: verify-claim mismatch coverage added with neutral actionable error and pending-state preservation.
  • (2026-03-03) Completed T015: revoke coverage added (verified claim transitions to revoked and active challenge invalidates).
  • (2026-03-03) Completed T016: conflict coverage added (verification blocked when another tenant already holds verified claim).
  • (2026-03-03) Completed T017: CE advisory add-domain behavior covered by save action persistence + normalized active domain assertions.
  • (2026-03-03) Completed T018: CE advisory remove-domain behavior covered by save action deactivation/removal assertions.
  • (2026-03-03) Completed T019: added EE runtime UI contract coverage asserting lifecycle claim rows render with status badges (Pending, Verified) from listMspSsoDomainClaims data.
  • (2026-03-03) Validation run for T019:
    • cd server && npx vitest run --coverage.enabled=false ../packages/integrations/src/components/settings/integrations/MspSsoLoginDomainsSettings.contract.test.tsx
  • (2026-03-03) Completed T020: EE settings test now asserts pending claims render DNS TXT verification instructions with host and value hints.
  • (2026-03-03) Validation run for T020:
    • cd server && npx vitest run --coverage.enabled=false ../packages/integrations/src/components/settings/integrations/MspSsoLoginDomainsSettings.contract.test.tsx
  • (2026-03-03) Completed T021: EE settings verification-failure path now checks neutral actionable error messaging and destructive feedback toast.
  • (2026-03-03) Validation run for T021:
    • cd server && npx vitest run --coverage.enabled=false ../packages/integrations/src/components/settings/integrations/MspSsoLoginDomainsSettings.contract.test.tsx
  • (2026-03-03) Completed T022: CE settings suite now asserts advisory-mode guidance copy is rendered for community deployments.
  • (2026-03-03) Validation run for T022:
    • cd server && npx vitest run --coverage.enabled=false src/test/unit/components/integrations/MspSsoLoginDomainsSettings.test.tsx
  • (2026-03-03) Completed T023: CE UI test now covers advisory add/remove controls end-to-end and asserts persisted payload ordering.
  • (2026-03-03) Validation run for T023:
    • cd server && npx vitest run --coverage.enabled=false src/test/unit/components/integrations/MspSsoLoginDomainsSettings.test.tsx
  • (2026-03-03) Completed T024: CE settings copy contract now explicitly asserts unmanaged-domain fallback to Nine Minds app-level providers.
  • (2026-03-03) Validation run for T024:
    • cd server && npx vitest run --coverage.enabled=false src/test/unit/components/integrations/MspSsoLoginDomainsSettings.test.tsx
  • (2026-03-03) Completed T025: discovery helper matrix tests now assert edition + claim lifecycle decisions drive tenant vs app source selection.
  • (2026-03-03) Validation run for T025:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T026: EE discovery with verified claim and tenant Google credentials returns tenant source + google provider.
  • (2026-03-03) Validation run for T026:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T027: EE discovery with verified claim and tenant Microsoft credentials returns tenant source + azure-ad provider.
  • (2026-03-03) Validation run for T027:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T028: EE discovery with pending claim returns app-level fallback providers only.
  • (2026-03-03) Validation run for T028:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T029: EE discovery with revoked claim returns app-level fallback providers only.
  • (2026-03-03) Validation run for T029:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T030: EE discovery with ambiguous domain ownership returns app-level fallback providers only.
  • (2026-03-03) Validation run for T030:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T031: CE discovery with advisory registered domain can return tenant-scoped provider eligibility.
  • (2026-03-03) Validation run for T031:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T032: CE discovery with unregistered domain returns app-level fallback providers.
  • (2026-03-03) Validation run for T032:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T033: Unresolved domain in both editions returns app-level fallback provider set.
  • (2026-03-03) Validation run for T033:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T034: Discover endpoint invalid-email path returns invariant neutral schema.
  • (2026-03-03) Validation run for T034:
    • cd server && npx vitest run --coverage.enabled=false src/app/api/auth/msp/sso/discover/route.test.ts
  • (2026-03-03) Completed T035: Discover endpoint rate-limit path returns same neutral schema and behavior.
  • (2026-03-03) Validation run for T035:
    • cd server && npx vitest run --coverage.enabled=false src/app/api/auth/msp/sso/discover/route.test.ts
  • (2026-03-03) Completed T036: Discover endpoint logging excludes raw email and keeps only safe metadata.
  • (2026-03-03) Validation run for T036:
    • cd server && npx vitest run --coverage.enabled=false src/app/api/auth/msp/sso/discover/route.test.ts
  • (2026-03-03) Completed T037: Resolver in EE with verified claim context selects tenant credential source.
  • (2026-03-03) Validation run for T037:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T038: Resolver in EE with non-verified claim context uses app fallback or generic failure per eligibility.
  • (2026-03-03) Validation run for T038:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T039: Resolver denies provider attempts outside discovered allow-list with generic response.
  • (2026-03-03) Validation run for T039:
    • cd server && npx vitest run --coverage.enabled=false src/app/api/auth/msp/sso/resolve/route.test.ts
  • (2026-03-03) Completed T040: Resolver stale discovery context is revalidated and cannot force unauthorized tenant source.
  • (2026-03-03) Validation run for T040:
    • cd server && npx vitest run --coverage.enabled=false src/app/api/auth/msp/sso/resolve/route.test.ts
  • (2026-03-03) Completed T041: Resolver invalid payload, rate-limit, and source-failure responses remain externally indistinguishable.
  • (2026-03-03) Validation run for T041:
    • cd server && npx vitest run --coverage.enabled=false src/app/api/auth/msp/sso/resolve/route.test.ts
  • (2026-03-03) Completed T042: Discovery cookie payload remains signed, short-lived, and free of provider secrets.
  • (2026-03-03) Validation run for T042:
    • cd server && npx vitest run --coverage.enabled=false src/app/api/auth/msp/sso/discover/route.test.ts
  • (2026-03-03) Completed T043: Resolution cookie payload remains signed, short-lived, and free of provider secrets.
  • (2026-03-03) Validation run for T043:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T044: MSP credentials login succeeds unchanged when domain claim states vary.
  • (2026-03-03) Validation run for T044:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/components/MspCredentialsFlow.contract.test.ts
  • (2026-03-03) Completed T045: Client portal signin flow remains unchanged and does not call MSP discovery endpoints.
  • (2026-03-03) Validation run for T045:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/components/ClientPortalAuthUnchanged.contract.test.ts
  • (2026-03-03) Completed T046: CE build wiring resolves MSP SSO entry to discovery-enabled provider buttons implementation.
  • (2026-03-03) Validation run for T046:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/components/ssoProviderButtons.ceEeParity.test.ts
  • (2026-03-03) Completed T047: MSP login form passes normalized email prop into SSO discovery component in both editions.
  • (2026-03-03) Validation run for T047:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/components/ssoProviderButtonsImport.test.ts
  • (2026-03-03) Completed T048: SSO buttons remain disabled for invalid email and while discovery is in flight.
  • (2026-03-03) Validation run for T048:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/components/SsoProviderButtons.msp.test.tsx
  • (2026-03-03) Completed T049: SSO buttons enable only providers returned by discovery response and keep unsupported buttons disabled.
  • (2026-03-03) Validation run for T049:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/components/SsoProviderButtons.msp.test.tsx
  • (2026-03-03) Completed T050: Disabled SSO button clicks never trigger resolver/start request.
  • (2026-03-03) Validation run for T050:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/components/SsoProviderButtons.msp.test.tsx
  • (2026-03-03) Completed T051: Remembered provider preference is only applied when provider remains eligible after discovery.
  • (2026-03-03) Validation run for T051:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/components/SsoProviderButtons.msp.test.tsx
  • (2026-03-03) Completed T052: Docs describe EE request-verify-revoke lifecycle and DNS ownership verification steps.
  • (2026-03-03) Validation run for T052:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoDocsContract.test.ts
  • (2026-03-03) Completed T053: Docs describe CE advisory registration behavior and non-blocking ownership model.
  • (2026-03-03) Validation run for T053:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoDocsContract.test.ts
  • (2026-03-03) Completed T054: Docs describe Nine Minds fallback provider prerequisites and unmanaged-domain behavior.
  • (2026-03-03) Validation run for T054:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoDocsContract.test.ts
  • (2026-03-03) Completed T055: DB-backed integration happy path: EE verified claim + tenant Microsoft credentials returns tenant source and ["azure-ad"].
  • (2026-03-03) Validation run for T055:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T056: DB-backed integration guard: EE pending claim with tenant credentials still returns app fallback source.
  • (2026-03-03) Validation run for T056:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T057: DB-backed integration guard: second EE tenant cannot verify takeover for already-verified domain.
  • (2026-03-03) Validation run for T057:
    • cd server && npx vitest run --coverage.enabled=false ../packages/integrations/src/actions/integrations/mspSsoDomainActions.test.ts
  • (2026-03-03) Completed T058: DB-backed integration guard: revoked EE claim no longer enables tenant takeover routing.
  • (2026-03-03) Validation run for T058:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T059: DB-backed integration CE advisory path: registered advisory domain can route to tenant source when tenant credentials exist.
  • (2026-03-03) Validation run for T059:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/lib/sso/mspSsoResolution.test.ts
  • (2026-03-03) Completed T060: Route contract preserves /auth/msp/signin entry path and callbackUrl passthrough under new lifecycle rules.
  • (2026-03-03) Validation run for T060:
    • cd server && npx vitest run --coverage.enabled=false ../packages/auth/src/components/MspSignInRoute.contract.test.ts