Files

40 lines
1.3 KiB
Go
Raw Permalink Normal View History

// Package devicebinding owns compatibility gates shared by all ownership writers.
// Generation advancement and claim fencing are enforced by the database trigger
// so background deletion and operator mutations cannot omit invalidation.
package devicebinding
import (
"context"
"errors"
"github.com/jackc/pgx/v5"
)
var ErrConfirmationRequired = errors.New("device physical confirmation workflow required")
type Queryer interface {
QueryRow(context.Context, string, ...any) pgx.Row
}
func RequireLegacy(ctx context.Context, q Queryer, deviceID string) error {
var mode string
err := q.QueryRow(ctx, `SELECT enrollment_mode FROM device WHERE id=$1::uuid`, deviceID).Scan(&mode)
if err != nil {
return err
}
if mode != "legacy" {
return ErrConfirmationRequired
}
return nil
}
func RequireUnboundForReset(ctx context.Context, q Queryer, deviceID string) error {
var allowed bool
err := q.QueryRow(ctx, `SELECT enrollment_mode='legacy' OR (NOT EXISTS(SELECT 1 FROM device_binding WHERE device_id=d.id AND unbound_at IS NULL) AND NOT EXISTS(SELECT 1 FROM device_account_binding WHERE device_id=d.id AND released_at IS NULL)) FROM device d WHERE id=$1::uuid`, deviceID).Scan(&allowed)
if err != nil {
return err
}
if !allowed {
return ErrConfirmationRequired
}
return nil
}