Split inactive profile state

Replace the binary profile ACTIVE/INACTIVE model with PENDING, ACTIVE,
and DEACTIVATED so invited-but-not-yet-activated members remain
assignable to assets, data, and risks instead of being treated like
deactivated users.

Add activated_at/deactivated_at timestamps and Mark* lifecycle helpers,
and update every transition (create, invite/re-invite, activation,
archive, SCIM, SAML, sessions, compliance-portal grant) to the new
states. Expose a multi-state states[] filter across coredata, GraphQL,
MCP, and the console owner pickers, which now request ACTIVE and
PENDING members.

A migration renames the membership_state enum, classifies existing
inactive profiles as PENDING from recent invitation activity, and
backfills the new timestamp columns.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-07-28 17:03:52 +02:00
parent 6b3913b189
commit 4a276e3ef7
29 changed files with 261 additions and 64 deletions

View File

@@ -24,7 +24,7 @@ import {
} from "react-relay";
import { graphql } from "relay-runtime";
import type { PeopleGraphQuery } from "#/__generated__/core/PeopleGraphQuery.graphql";
import type { PeopleGraphQuery, ProfileFilter } from "#/__generated__/core/PeopleGraphQuery.graphql";
/* eslint-disable relay/unused-fields */
@@ -57,11 +57,15 @@ export function usePeople(
organizationId: string,
{ contractEnded }: { contractEnded?: boolean } = {},
) {
const filter: ProfileFilter = contractEnded !== undefined
? { contractEnded, states: ["ACTIVE", "PENDING"] }
: { states: ["ACTIVE", "PENDING"] };
const data = useLazyLoadQuery<PeopleGraphQuery>(
peopleQuery,
{
organizationId: organizationId,
filter: contractEnded !== undefined ? { contractEnded } : null,
filter,
},
{ fetchPolicy: "network-only" },
);