Documentation
¶
Overview ¶
Package models holds the domain types shared by the store, estimator and web layers.
Index ¶
- Constants
- Variables
- func DefaultRanking() []string
- func JobActive(state string) bool
- func NormalizeEmail(email string) string
- func NormalizeRanking(in []string) []string
- func ValidMethod(key string) bool
- type AccessToken
- type AuditEvent
- type AuthProvider
- type Completion
- type DexaScan
- type Identity
- type Job
- type JobFilter
- type JobKindStats
- type JobSchedule
- type LeaseRequest
- type MethodInfo
- type NewJob
- type Passkey
- type ScaleReading
- type Session
- type TOTP
- type User
- type WorkerInstance
Constants ¶
const ( JobQueued = "queued" JobRunning = "running" JobSucceeded = "succeeded" JobFailed = "failed" JobCanceled = "canceled" JobExpired = "expired" )
The states of a worker job. A job is queued until a worker leases it, then running; it ends as succeeded, failed (given up, kept for the administrator), canceled or expired (never started in time).
const ( JobOriginUser = "user" // a button in the pages JobOriginAPI = "api" // the public API JobOriginSchedule = "schedule" // the scheduler JobOriginAdmin = "admin" // an administrator )
Where a job came from.
const ( OutcomeOK = "ok" // done OutcomeRetry = "retry" // a temporary problem: try again later, while attempts are left OutcomeFail = "fail" // a permanent problem: do not try again )
How a worker ended an attempt.
const ( MinJobPriority = 1 MaxJobPriority = 100 DefaultJobPriority = 50 )
Job priorities are 1 (lowest) to 100 (highest); administrators' jobs always go first.
const ( MethodScale = "scale" // bioimpedance smart scale (Withings, manual entry from a scale) MethodHydrostatic = "hydrostatic" // underwater weighing MethodBodPod = "bodpod" // air displacement plethysmography MethodCaliper = "caliper" // skinfold calipers MethodTape = "tape" // tape measure / Navy formula MethodVisualAI = "visual-ai" // AI estimate from photos // MethodManualEntry is a value typed into an app (for example a body fat % entered by hand in // the Withings app): how it was measured is unknown, so it ranks last by default. MethodManualEntry = "manual-entry" )
Measurement methods: how a scale/body-composition reading was obtained.
const ( RoleUser = "user" RoleAdmin = "admin" )
User roles.
const ( ProviderKindOIDC = "oidc" // OpenID Connect with discovery, e.g. Google ProviderKindApple = "apple" // Sign in with Apple: OIDC with a generated client secret ProviderKindOAuth2 = "oauth2" // plain OAuth 2.0 with a userinfo endpoint )
Kinds of external sign-in provider.
const ProviderLocal = "local"
ProviderLocal is the identity provider of username and password sign-in.
const ProviderPasskey = "passkey"
ProviderPasskey is the pseudo-provider of passkey sign-in. Like ProviderLocal it cannot be used as the short name of an external provider.
const SourceManual = "manual"
SourceManual is the source of readings entered by hand.
Variables ¶
var Methods = []MethodInfo{ {MethodHydrostatic, "Hydrostatic weighing"}, {MethodBodPod, "BodPod"}, {MethodCaliper, "Skinfold caliper"}, {MethodScale, "Smart scale (Withings, manual)"}, {MethodTape, "Tape / Navy formula"}, {MethodVisualAI, "Visual AI"}, {MethodManualEntry, "Typed into an app (unknown method)"}, }
Methods lists all methods in the default accuracy order (most accurate first).
Functions ¶
func DefaultRanking ¶
func DefaultRanking() []string
DefaultRanking returns the method keys in the default accuracy order.
func NormalizeEmail ¶
NormalizeEmail returns the canonical form of an e-mail address, used to compare addresses.
func NormalizeRanking ¶
NormalizeRanking drops unknown and duplicate keys and appends missing methods in default order, so the result always contains every method exactly once.
func ValidMethod ¶
ValidMethod reports whether key is a known method.
Types ¶
type AccessToken ¶
type AccessToken struct {
ID int64
UserID int64
Name string
Prefix string // the first characters of the token, to recognise it in lists
Hash string
CreatedAt time.Time
LastUsedAt *time.Time
ExpiresAt *time.Time
}
AccessToken is a personal access token. Only a hash of the token is stored.
type AuditEvent ¶
type AuditEvent struct {
ID int64 `json:"id"`
At time.Time `json:"at"`
ActorID *int64 `json:"actor_id"` // who did it; nil for anonymous requests and deleted users
TargetID *int64 `json:"target_id"` // whose account it concerns; nil when none or deleted
Action string `json:"action"`
Detail string `json:"detail,omitempty"`
IP string `json:"ip,omitempty"` // cleared when the user is deleted, dropped after the retention period
}
AuditEvent records something security-relevant that happened: a sign-in, a change to an account, an export or an administrator's action. Detail never holds credentials or other personal data.
type AuthProvider ¶
type AuthProvider struct {
Slug string
Label string
Kind string
Issuer string // OIDC issuer URL
AuthURL string // plain OAuth 2.0 endpoints
TokenURL string
UserinfoURL string
ClientID string
ClientSecret string // for Apple: the PEM private key the client secret is signed with
AppleTeamID string
AppleKeyID string
Scopes string // space separated
SubjectClaim string // plain OAuth 2.0: the userinfo field that identifies the account
NameClaim string // preferred claim for naming new users
AllowSignup bool // create an account on the first sign-in
CreatedAt time.Time
}
AuthProvider is an external sign-in provider added by an administrator.
type Completion ¶
type Completion struct {
Outcome string // OutcomeOK, OutcomeRetry or OutcomeFail
Result string
Error string
// RetryAt is when a retry may run; the backend computes it from its backoff settings.
RetryAt time.Time
}
Completion is how a worker ends an attempt.
type DexaScan ¶
type DexaScan struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
MeasuredAt time.Time `json:"measured_at"`
WeightKg *float64 `json:"weight_kg,omitempty"`
FatRatioPct *float64 `json:"fat_ratio_pct,omitempty"`
FatMassKg *float64 `json:"fat_mass_kg,omitempty"`
FatFreeMassKg *float64 `json:"fat_free_mass_kg,omitempty"`
LeanMassKg *float64 `json:"lean_mass_kg,omitempty"`
BoneMassKg *float64 `json:"bone_mass_kg,omitempty"`
VisceralFatMassKg *float64 `json:"visceral_fat_mass_kg,omitempty"`
BMDGCm2 *float64 `json:"bmd_g_cm2,omitempty"`
TScore *float64 `json:"t_score,omitempty"`
ZScore *float64 `json:"z_score,omitempty"`
AndroidFatPct *float64 `json:"android_fat_pct,omitempty"`
GynoidFatPct *float64 `json:"gynoid_fat_pct,omitempty"`
Notes string `json:"notes,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
DexaScan is a single DEXA scan result.
type Identity ¶
type Identity struct {
UserID int64
Provider string
// Subject identifies the account at the provider. For ProviderLocal it is the user id.
Subject string
// Secret holds the password hash for ProviderLocal and is empty otherwise.
Secret string
CreatedAt time.Time
}
Identity is one way a user can sign in, independent of the user record itself.
type Job ¶
type Job struct {
ID int64
PublicID string // the identifier used outside the database
UserID int64
Kind string // "<provider>.<action>", such as "withings.import"
Origin string
// Interactive jobs are waited for by a person, so they go before background ones of the same priority.
Interactive bool
// DedupeKey allows one active (queued or running) job per key; empty means no limit.
DedupeKey string
State string
// Payload holds the job's parameters, and Result what it produced. The store encrypts both.
// Payload is cleared when the job ends, because it can hold a credential.
Payload string
Progress string
Result string
Error string
Attempts int
MaxAttempts int
Timeout time.Duration // the hard limit of one attempt
CreatedAt time.Time
RunAfter time.Time
ExpiresAt *time.Time // a queued job still waiting after this is expired instead of run late
StartedAt *time.Time
FinishedAt *time.Time
UpdatedAt time.Time
LeaseOwner string
LeaseUntil *time.Time
DeadlineAt *time.Time
CancelRequested bool
}
Job is one unit of work for a worker, such as importing a user's Withings measurements. The backend owns the queue; a worker only ever sees a job inside a lease.
type JobFilter ¶
type JobFilter struct {
UserID int64 // 0: every user
Kinds []string // empty: every kind
States []string // empty: every state
Limit int // 0: 100
}
JobFilter selects jobs for a listing, newest first.
type JobKindStats ¶
type JobKindStats struct {
Kind string
Queued int
Running int
Failed int // that ended as failed in the period asked for
}
JobKindStats counts the jobs of one kind.
type JobSchedule ¶
type JobSchedule struct {
UserID int64
Kind string
LastEnqueuedAt *time.Time
ConsecutiveFailures int
// PausedReason is set when the scheduler stopped enqueuing for the user after repeated failures.
PausedReason string
}
JobSchedule is the scheduler's memory about one user and kind.
type LeaseRequest ¶
type LeaseRequest struct {
Kinds []string
Owner string // the worker's name, for the administrator
TokenHash string // hash of the secret that proves later calls come from the leaseholder
LeaseFor time.Duration // how long the lease lasts without a heartbeat
// MaxRunning limits how many jobs of a kind run at once, in all workers together; a kind that is
// missing is not limited. Paused kinds are never leased.
MaxRunning map[string]int
Paused []string
}
LeaseRequest asks for the next job a worker may run.
type MethodInfo ¶
MethodInfo describes a measurement method for forms.
type NewJob ¶
type NewJob struct {
UserID int64
Kind string
Origin string
Interactive bool
DedupeKey string
Payload string
MaxAttempts int
Timeout time.Duration
RunAfter time.Time // zero means now
ExpiresAt *time.Time // nil means never
}
NewJob describes a job to queue.
type Passkey ¶
type Passkey struct {
CredentialID string // base64url
UserID int64
Name string
Credential string // JSON of the WebAuthn credential: public key, transports, flags
SignCount uint32
CreatedAt time.Time
LastUsedAt *time.Time
}
Passkey is a WebAuthn credential of a user, used to sign in without a password.
type ScaleReading ¶
type ScaleReading struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"`
MeasuredAt time.Time `json:"measured_at"`
WeightKg *float64 `json:"weight_kg,omitempty"`
FatRatioPct *float64 `json:"fat_ratio_pct,omitempty"`
FatMassKg *float64 `json:"fat_mass_kg,omitempty"`
FatFreeMassKg *float64 `json:"fat_free_mass_kg,omitempty"`
MuscleMassKg *float64 `json:"muscle_mass_kg,omitempty"`
HydrationKg *float64 `json:"hydration_kg,omitempty"`
BoneMassKg *float64 `json:"bone_mass_kg,omitempty"`
VisceralFatIndex *float64 `json:"visceral_fat_index,omitempty"`
Source string `json:"source"`
Method string `json:"method"`
AthleteMode bool `json:"athlete_mode"`
ExternalID *string `json:"external_id,omitempty"`
Notes string `json:"notes,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
ScaleReading is a single smart-scale measurement. Fields are aligned with Withings measure types. Source and ExternalID make imports idempotent (e.g. Source "withings", ExternalID = grpid).
type Session ¶
type Session struct {
UserID int64
Method string // how the user signed in: ProviderLocal, ProviderPasskey or a provider slug
CreatedAt time.Time
ExpiresAt time.Time
}
Session is a signed-in browser session. The token itself is never stored, only its hash.
type TOTP ¶
type TOTP struct {
UserID int64
Secret string // the shared secret, decrypted
LastStep int64 // newest 30-second step that was accepted
Confirmed bool // false while the user is still setting it up
ConfirmedAt time.Time
CreatedAt time.Time
}
TOTP is a user's time-based one-time password setup (two-step verification).
type User ¶
type User struct {
ID int64 `json:"id"`
Name string `json:"name"`
Role string `json:"role"`
CreatedAt time.Time `json:"created_at"`
// Email signs the user in and identifies them, unique per user. It is empty for accounts that
// only sign in through a provider that did not vouch for an address. External providers never
// match accounts by it.
Email string `json:"email"`
HeightCm *float64 `json:"height_cm,omitempty"`
// Timezone is an IANA time zone name such as "Europe/Amsterdam". It decides which calendar
// day a reading belongs to and how manual date-times are read and shown. Empty means UTC.
Timezone string `json:"timezone"`
// AthleteDefault presets athlete mode for new readings and imports.
AthleteDefault bool `json:"athlete_default"`
// MethodRanking lists methods most accurate first. Always contains every method.
MethodRanking []string `json:"method_ranking"`
// HiddenColumns lists the daily table columns the user has hidden.
HiddenColumns []string `json:"-"`
// StrengthLevelAuto is set by an administrator. It lets the user store their Strength Level
// login and sync body readings to it automatically.
StrengthLevelAuto bool `json:"-"`
// StrengthLevelBulk additionally allows the multi-day sync on the settings page. It needs
// StrengthLevelAuto.
StrengthLevelBulk bool `json:"-"`
// JobPriority (1-100) orders the user's worker jobs among those of other users: a higher number
// goes first. Administrators' jobs always go before everyone's. Set by an administrator.
JobPriority int `json:"-"`
// DataVersion changes whenever the scans, readings or settings that estimates are computed
// from change, in any way and from any process. Cached results are valid for one version.
DataVersion int64 `json:"-"`
}
User is a person whose measurements are tracked.