devicepairing

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2026 License: AGPL-3.0 Imports: 15 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrPairingNotFound is returned when the pairing code or ID does not match any record.
	ErrPairingNotFound = errors.New("device pairing not found")

	// ErrPairingNotPending is returned when the pairing is already used or expired at delete time.
	ErrPairingNotPending = errors.New("device pairing is no longer pending")

	ErrPairingNotClaimable = errors.New("cannot claim an invalid or expired pairing")
	ErrPairingExpired      = errors.New("pairing expired")
)

Functions

This section is empty.

Types

type ClaimResult

type ClaimResult struct {
	ServerURL           string
	IntervalSeconds     int
	AppBiometricEnabled bool
	AppSettingsLocked   bool
	RawAPIKey           string // Plaintext — send to app, never stored again.
}

ClaimResult is returned after a successful claim: the config payload and the one-time API key.

type CreatePairingRequest

type CreatePairingRequest struct {
	DeviceID            ids.DeviceID
	HeartbeatServerURL  string
	IntervalSeconds     int
	AppBiometricEnabled bool
	AppSettingsLocked   bool
	ExpiresInHours      int
	ExpiresAt           time.Time
	PairingCode         string
}

CreatePairingRequest carries the admin-provided fields for a new pairing.

type DevicePairing

type DevicePairing struct {
	ID ids.DevicePairingID

	DeviceID ids.DeviceID

	// PairingCode is the full base64url-encoded code delivered to the app.
	PairingCode string

	HeartbeatServerURL       string
	HeartbeatIntervalSeconds int
	AppBiometricEnabled      bool
	AppSettingsLocked        bool

	ExpiresAt time.Time
	CreatedAt time.Time
	// UpdatedAt is when the status last changed (equals CreatedAt for pending pairings).
	UpdatedAt time.Time

	// Status is the derived lifecycle state; expired is computed from ExpiresAt, never stored.
	Status PairingStatus
}

DevicePairing is the domain model for a pairing record.

func (*DevicePairing) ToClaimResult

func (p *DevicePairing) ToClaimResult(rawAPIKey string) ClaimResult

type HTTPHandler

type HTTPHandler struct {
	// contains filtered or unexported fields
}

HTTPHandler implements the device pairing subset of httpapi.StrictServerInterface.

func NewHTTPHandler

func NewHTTPHandler(svc *Service, logger *slog.Logger) *HTTPHandler

type PairingFilter

type PairingFilter struct {
	DeviceID ids.DeviceID
	// IncludeAll includes all statuses in addition to pending ones.
	IncludeAll bool
}

PairingFilter controls which pairings are returned by ListPairings.

type PairingStatus

type PairingStatus string

PairingStatus is the full lifecycle state of a device pairing.

const (
	StatusPending     PairingStatus = "pending"
	StatusUsed        PairingStatus = "used"
	StatusExpired     PairingStatus = "expired"
	StatusInvalidated PairingStatus = "invalidated"
	StatusReplaced    PairingStatus = "replaced"
)

func EvalStatus

func EvalStatus(stored string, expiresAt time.Time) PairingStatus

EvalStatus derives the full PairingStatus from a stored status string and expiry time. Use this in cross-domain queries that need to surface pairing status without a full Repository call (e.g. the device list view).

type Repository

type Repository struct {
	// contains filtered or unexported fields
}

Repository handles all database operations for the devicepairing package.

func NewRepository

func NewRepository(db *database.DB) *Repository

func (*Repository) ClaimPairing

func (r *Repository) ClaimPairing(ctx context.Context, id ids.DevicePairingID) (*DevicePairing, error)

ClaimPairing marks a pairing as used.

func (*Repository) CreatePairing

func (r *Repository) CreatePairing(ctx context.Context, req CreatePairingRequest) (*DevicePairing, error)

CreatePairing inserts a new device pairing record with status=pending.

func (*Repository) GetPairing

func (r *Repository) GetPairing(ctx context.Context, id ids.DevicePairingID) (*DevicePairing, error)

GetPairing returns a device pairing by ID.

func (*Repository) GetPairingByCode

func (r *Repository) GetPairingByCode(ctx context.Context, code string) (*DevicePairing, error)

GetPairingByCode returns a device pairing by its pairing code.

func (*Repository) InvalidatePairing

func (r *Repository) InvalidatePairing(ctx context.Context, deviceID ids.DeviceID, id ids.DevicePairingID) error

InvalidatePairing soft-cancels a pending pairing by setting status=invalidated. Returns ErrPairingNotFound if no matching pending record exists.

func (*Repository) ListPairings

func (r *Repository) ListPairings(ctx context.Context, filter PairingFilter) ([]DevicePairing, error)

ListPairings returns device pairings for a device, filtered by the given options. When filter.IncludeAll is false, only claimable (pending, not yet expired) pairings are returned.

func (*Repository) ReplacePendingPairings

func (r *Repository) ReplacePendingPairings(ctx context.Context, deviceID ids.DeviceID) error

ReplacePendingPairings marks all pending pairings for the given device as replaced. Called inside a transaction before creating a new pairing.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service contains all business logic for the devicepairing package.

func NewService

func NewService(repo repository, tx transactor, keyManager apiKeyManager, logger *slog.Logger) *Service

func (*Service) ClaimPairing

func (s *Service) ClaimPairing(ctx context.Context, code string) (*ClaimResult, error)

ClaimPairing validates and redeems a pairing code. On success it returns the configuration payload and the plaintext device API key (one-time only).

func (*Service) CreatePairing

func (s *Service) CreatePairing(ctx context.Context, req CreatePairingRequest) (*DevicePairing, error)

CreatePairing generates a pairing code and persists the pairing record. Any existing pending pairings for the same device are replaced atomically.

func (*Service) GetPairing

func (s *Service) GetPairing(ctx context.Context, id ids.DevicePairingID) (*DevicePairing, error)

GetPairing returns a single pairing by ID.

func (*Service) InvalidatePairing

func (s *Service) InvalidatePairing(ctx context.Context, deviceID ids.DeviceID, id ids.DevicePairingID) error

InvalidatePairing soft-deletes an unclaimed pairing.

func (*Service) ListPairings

func (s *Service) ListPairings(ctx context.Context, filter PairingFilter) ([]DevicePairing, error)

ListPairings returns pairings according to the given filter.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL