Rename user archive action to deactivate

"Archive" was misleading for users: the action sets a profile to
DEACTIVATED while keeping the person in the organization. Rename it to
"deactivate" across the API, CLI, MCP, n8n, and console UI.

Consolidate the two overlapping operations into a single deactivateUser
backed by the fuller, guarded logic (SCIM guard, last-active-owner
guard, invitation expiry, signature cancellation, membership update,
webhook) and authorized via iam:membership-profile:deactivate. Remove
the archiveUser surface and the thin state-only deactivate path.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-07-28 17:30:14 +02:00
parent 99c3235b46
commit b10fc55b7f
14 changed files with 130 additions and 208 deletions

View File

@@ -18,7 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package archive
package deactivate
import (
"fmt"
@@ -29,34 +29,34 @@ import (
"go.probo.inc/probo/pkg/cmd/cmdutil"
)
const archiveMutation = `
mutation($input: ArchiveUserInput!) {
archiveUser(input: $input) {
archivedProfileId
const deactivateMutation = `
mutation($input: DeactivateUserInput!) {
deactivateUser(input: $input) {
success
}
}
`
func NewCmdArchive(f *cmdutil.Factory) *cobra.Command {
func NewCmdDeactivate(f *cmdutil.Factory) *cobra.Command {
var (
flagOrg string
flagYes bool
)
cmd := &cobra.Command{
Use: "archive <id>",
Short: "Archive a user",
Use: "deactivate <id>",
Short: "Deactivate a user",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
if !flagYes {
if !f.IOStreams.IsInteractive() {
return fmt.Errorf("cannot archive user: confirmation required, use --yes to confirm")
return fmt.Errorf("cannot deactivate user: confirmation required, use --yes to confirm")
}
var confirmed bool
err := huh.NewConfirm().
Title(fmt.Sprintf("Archive user %s?", args[0])).
Title(fmt.Sprintf("Deactivate user %s?", args[0])).
Value(&confirmed).
Run()
if err != nil {
@@ -95,7 +95,7 @@ func NewCmdArchive(f *cmdutil.Factory) *cobra.Command {
)
_, err = client.Do(
archiveMutation,
deactivateMutation,
map[string]any{
"input": map[string]any{
"organizationId": flagOrg,
@@ -107,7 +107,7 @@ func NewCmdArchive(f *cmdutil.Factory) *cobra.Command {
return err
}
_, _ = fmt.Fprintf(f.IOStreams.Out, "Archived user %s\n", args[0])
_, _ = fmt.Fprintf(f.IOStreams.Out, "Deactivated user %s\n", args[0])
return nil
},

View File

@@ -23,7 +23,7 @@ package user
import (
"github.com/spf13/cobra"
"go.probo.inc/probo/pkg/cmd/cmdutil"
"go.probo.inc/probo/pkg/cmd/user/archive"
"go.probo.inc/probo/pkg/cmd/user/deactivate"
"go.probo.inc/probo/pkg/cmd/user/list"
"go.probo.inc/probo/pkg/cmd/user/remove"
"go.probo.inc/probo/pkg/cmd/user/view"
@@ -37,7 +37,7 @@ func NewCmdUser(f *cmdutil.Factory) *cobra.Command {
cmd.AddCommand(list.NewCmdList(f))
cmd.AddCommand(view.NewCmdView(f))
cmd.AddCommand(archive.NewCmdArchive(f))
cmd.AddCommand(deactivate.NewCmdDeactivate(f))
cmd.AddCommand(remove.NewCmdRemove(f))
return cmd