Add soft delete for revoked devices

Admins could only revoke devices, so never-enrolled and revoked
inventory rows piled up with no way to remove them. Soft-delete
is limited to REVOKED devices (revoke first), and ITAM GC now
hard-deletes PENDING/REVOKED orphans with no API key, postures,
or valid enrollment token—including user tombstones without
history.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
This commit is contained in:
Ludovic Vielle
2026-07-30 10:11:08 +02:00
parent 41da4bbad1
commit 7731566c68
23 changed files with 773 additions and 61 deletions

View File

@@ -239,6 +239,31 @@ func (r *mutationResolver) RevokeDevice(ctx context.Context, input types.RevokeD
return &types.RevokeDevicePayload{Device: types.NewDevice(d)}, nil
}
// DeleteDevice is the resolver for the deleteDevice field.
func (r *mutationResolver) DeleteDevice(ctx context.Context, input types.DeleteDeviceInput) (*types.DeleteDevicePayload, error) {
scope, err := r.authorize(ctx, input.DeviceID, itam.ActionDeviceDelete)
if err != nil {
return nil, err
}
d, err := r.itam.DeleteDevice(ctx, scope, input.DeviceID)
if err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return nil, gqlutils.NotFound(ctx, err)
}
if errors.Is(err, itam.ErrDeviceNotDeletable) {
return nil, gqlutils.Conflict(ctx, err)
}
r.logger.ErrorCtx(ctx, "cannot delete device", log.Error(err))
return nil, gqlutils.Internal(ctx)
}
return &types.DeleteDevicePayload{DeletedDeviceID: d.ID}, nil
}
// SetDeviceOwner is the resolver for the setDeviceOwner field.
func (r *mutationResolver) SetDeviceOwner(ctx context.Context, input types.SetDeviceOwnerInput) (*types.SetDeviceOwnerPayload, error) {
scope, err := r.authorize(ctx, input.DeviceID, itam.ActionDeviceAssignOwner)

View File

@@ -237,6 +237,10 @@ type RevokeDevicePayload {
device: Device!
}
type DeleteDevicePayload {
deletedDeviceId: ID!
}
type SetDeviceOwnerPayload {
device: Device!
}
@@ -254,6 +258,10 @@ input RevokeDeviceInput {
deviceId: ID!
}
input DeleteDeviceInput {
deviceId: ID!
}
input SetDeviceOwnerInput {
deviceId: ID!
ownerId: ID
@@ -263,6 +271,7 @@ extend type Mutation {
enrollDevice(input: EnrollDeviceInput!): CreateDevicePayload!
createDevice(input: CreateDeviceInput!): CreateDevicePayload!
revokeDevice(input: RevokeDeviceInput!): RevokeDevicePayload!
deleteDevice(input: DeleteDeviceInput!): DeleteDevicePayload!
setDeviceOwner(
input: SetDeviceOwnerInput!
): SetDeviceOwnerPayload!