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

@@ -21,15 +21,21 @@
package coredata
import (
"database/sql/driver"
"encoding"
"fmt"
"strings"
)
type ProfileState string
type (
ProfileState string
ProfileStateValues []ProfileState
)
const (
ProfileStateActive ProfileState = "ACTIVE"
ProfileStateInactive ProfileState = "INACTIVE"
ProfileStatePending ProfileState = "PENDING"
ProfileStateActive ProfileState = "ACTIVE"
ProfileStateDeactivated ProfileState = "DEACTIVATED"
)
var (
@@ -40,16 +46,18 @@ var (
func ProfileStates() []ProfileState {
return []ProfileState{
ProfileStatePending,
ProfileStateActive,
ProfileStateInactive,
ProfileStateDeactivated,
}
}
func (v ProfileState) IsValid() bool {
switch v {
case
ProfileStatePending,
ProfileStateActive,
ProfileStateInactive:
ProfileStateDeactivated:
return true
}
@@ -74,3 +82,24 @@ func (v *ProfileState) UnmarshalText(text []byte) error {
return nil
}
func (states ProfileStateValues) Value() (driver.Value, error) {
if len(states) == 0 {
return nil, nil
}
var result strings.Builder
result.WriteString("{")
for i, state := range states {
if i > 0 {
result.WriteString(",")
}
fmt.Fprintf(&result, "%q", state.String())
}
result.WriteString("}")
return result.String(), nil
}