Documentation
¶
Index ¶
- Constants
- Variables
- func PairingStatusToAPI(s PairingStatus) httpapi.DevicePairingStatus
- type ClaimResult
- type CreatePairingRequest
- type DevicePairing
- type HTTPHandler
- func (h *HTTPHandler) ClaimPairing(ctx context.Context, request httpapi.ClaimPairingRequestObject) (httpapi.ClaimPairingResponseObject, error)
- func (h *HTTPHandler) CreateDevicePairing(ctx context.Context, request httpapi.CreateDevicePairingRequestObject) (httpapi.CreateDevicePairingResponseObject, error)
- func (h *HTTPHandler) DeleteDevicePairing(ctx context.Context, request httpapi.DeleteDevicePairingRequestObject) (httpapi.DeleteDevicePairingResponseObject, error)
- func (h *HTTPHandler) ListDevicePairings(ctx context.Context, request httpapi.ListDevicePairingsRequestObject) (httpapi.ListDevicePairingsResponseObject, error)
- type PairingFilter
- type PairingStatus
- type Repository
- func (r *Repository) ClaimPairing(ctx context.Context, id ids.DevicePairingID) (*DevicePairing, error)
- func (r *Repository) CreatePairing(ctx context.Context, req CreatePairingRequest) (*DevicePairing, error)
- func (r *Repository) GetPairingByCode(ctx context.Context, code string) (*DevicePairing, error)
- func (r *Repository) InvalidatePairing(ctx context.Context, deviceID ids.DeviceID, id ids.DevicePairingID) error
- func (r *Repository) ListPairings(ctx context.Context, filter PairingFilter) ([]DevicePairing, error)
- func (r *Repository) PairingsForDevices(ctx context.Context, deviceIDs []ids.DeviceID) (map[ids.DeviceID]httpapi.DevicePairingSummary, error)
- func (r *Repository) ReplacePendingPairings(ctx context.Context, deviceID ids.DeviceID) error
- type Service
- func (s *Service) ClaimPairing(ctx context.Context, code string) (*ClaimResult, error)
- func (s *Service) CreatePairing(ctx context.Context, req CreatePairingRequest) (*DevicePairing, error)
- func (s *Service) InvalidatePairing(ctx context.Context, deviceID ids.DeviceID, id ids.DevicePairingID) error
- func (s *Service) ListPairings(ctx context.Context, filter PairingFilter) ([]DevicePairing, error)
Constants ¶
const ( AttrKeyComponent = logging.AttrKeyComponent AttrKeyOperation = logging.AttrKeyOperation AttrKeyError = logging.AttrKeyError )
Slog attribute key names for the device pairing domain. Use these constants when logging so keys are consistent and typo-safe across handlers and services.
Variables ¶
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 ¶
func PairingStatusToAPI ¶ added in v0.6.0
func PairingStatusToAPI(s PairingStatus) httpapi.DevicePairingStatus
PairingStatusToAPI converts the domain pairing status to its API representation. The exhaustive linter fails this switch when a new PairingStatus value is added without a corresponding case here.
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
func (*HTTPHandler) ClaimPairing ¶
func (h *HTTPHandler) ClaimPairing(ctx context.Context, request httpapi.ClaimPairingRequestObject) (httpapi.ClaimPairingResponseObject, error)
func (*HTTPHandler) CreateDevicePairing ¶
func (h *HTTPHandler) CreateDevicePairing(ctx context.Context, request httpapi.CreateDevicePairingRequestObject) (httpapi.CreateDevicePairingResponseObject, error)
func (*HTTPHandler) DeleteDevicePairing ¶
func (h *HTTPHandler) DeleteDevicePairing(ctx context.Context, request httpapi.DeleteDevicePairingRequestObject) (httpapi.DeleteDevicePairingResponseObject, error)
func (*HTTPHandler) ListDevicePairings ¶
func (h *HTTPHandler) ListDevicePairings(ctx context.Context, request httpapi.ListDevicePairingsRequestObject) (httpapi.ListDevicePairingsResponseObject, error)
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) 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) PairingsForDevices ¶ added in v0.6.0
func (r *Repository) PairingsForDevices(ctx context.Context, deviceIDs []ids.DeviceID) (map[ids.DeviceID]httpapi.DevicePairingSummary, error)
PairingsForDevices returns the latest pairing of each given device, keyed by device id. Devices that have never been paired are absent from the map.
func (*Repository) ReplacePendingPairings ¶
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 (*Service) ClaimPairing ¶
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) 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.