Documentation
¶
Index ¶
- Constants
- Variables
- func ContainsControlChar(s string) bool
- func IsTimeMetric(metric string) bool
- func IsValidClassType(ct ClassType) bool
- func IsValidCrewRole(role CrewRole) bool
- func IsValidMetric(metric string) bool
- func ValidateAircraftTextFields(a *Aircraft) error
- func ValidateContactTextFields(ct *Contact) error
- func ValidateCredentialTextFields(cr *Credential) error
- func ValidateFlightTextFields(f *Flight) error
- func ValidateLicenseTextFields(l *License) error
- func ValidateOptionalStringLength(fieldName string, value *string, maxLen int) error
- func ValidateStringLength(fieldName, value string, maxLen int) error
- type Aircraft
- type AircraftRecencyRow
- type AircraftStats
- type AircraftTypeStats
- type ApproachEntry
- type BackupDestination
- type BackupDestinationStatus
- type BackupRun
- type BackupRunStatus
- type BackupRunTrigger
- type BackupSchedule
- type ClassRating
- type ClassType
- type Contact
- type Credential
- type CredentialType
- type CrewRole
- type CurrencyData
- type CurrencyFilter
- type CurrencyRequirement
- type CurrencyWindow
- type CustomCurrencyRule
- type CustomCurrencyRuleBody
- type EmailVerificationToken
- type Flight
- type FlightBaseline
- type FlightCrewMember
- type FlightSession
- type FlightSignature
- type FlightStatistics
- type License
- type NotificationCategory
- type NotificationLog
- type NotificationPreferences
- type PasswordResetToken
- type RefreshToken
- type SignatureMethod
- type SignatureStatus
- type User
- type WebAuthnCredential
- type WebAuthnSession
Constants ¶
const ( FlightSessionStatusOpen = "open" FlightSessionStatusCompleted = "completed" FlightSessionStatusDiscarded = "discarded" )
Flight session status values
const ( FlightSessionEventOffBlock = "offblock" FlightSessionEventTakeoff = "takeoff" FlightSessionEventLanding = "landing" FlightSessionEventOnBlock = "onblock" )
Flight session event types
const ( MinSignatureRequestExpiryHours = 1 MaxSignatureRequestExpiryHours = 24 * 30 // 30 days DefaultSignatureRequestExpiryHours = 24 * 7 // 7 days )
MinSignatureRequestExpiryHours / MaxSignatureRequestExpiryHours clamp the caller-supplied expiry window for a deferred signature request.
const MaxFlightSessionDuration = 24 * time.Hour
MaxFlightSessionDuration is the longest off-block → on-block span accepted when completing a session. Anything longer is almost certainly a forgotten session that should be discarded instead.
const MaxSignatureImageBytes = 500 * 1024
MaxSignatureImageBytes bounds the size of an uploaded signature image (decoded PNG bytes) to keep the flight_signatures table well-behaved.
Variables ¶
var ( // Flight validation errors ErrInvalidTimeDistribution = errors.New("PIC and dual time are mutually exclusive") ErrInvalidNightTime = errors.New("night time exceeds total time") ErrInvalidIFRTime = errors.New("IFR time exceeds total time") ErrNegativeTime = errors.New("flight times cannot be negative") ErrNegativeLandings = errors.New("landings cannot be negative") // Aircraft validation errors ErrAircraftRegistrationRequired = errors.New("aircraft registration is required") ErrAircraftTypeRequired = errors.New("aircraft type is required") ErrAircraftMakeRequired = errors.New("aircraft make is required") ErrAircraftModelRequired = errors.New("aircraft model is required") ErrAircraftInvalidEngineType = errors.New("invalid engine type") )
var ( ErrNoOpenFlightSession = errors.New("no open flight session") ErrInvalidFlightSessionData = errors.New("invalid flight session data") ErrFlightSessionTimeOrder = errors.New("flight session event times are out of order") ErrFlightSessionTooLong = errors.New("flight session exceeds maximum duration") ErrFlightSessionMissingReg = errors.New("aircraft registration is required to complete a flight session") )
Flight session errors
var AllNotificationCategories = pq.StringArray{ string(NotifCategoryCredentialMedical), string(NotifCategoryCredentialLanguage), string(NotifCategoryCredentialSecurity), string(NotifCategoryCredentialOther), string(NotifCategoryRatingExpiry), string(NotifCategoryCurrencyPassenger), string(NotifCategoryCurrencyNight), string(NotifCategoryCurrencyInstrument), string(NotifCategoryCurrencyFlightReview), string(NotifCategoryCurrencyRevalidation), }
AllNotificationCategories is the default set of all categories (all enabled)
var CountMetrics = map[string]bool{ "flights": true, "landings": true, "day_landings": true, "night_landings": true, "takeoffs": true, "day_takeoffs": true, "night_takeoffs": true, "approaches": true, "holds": true, }
CountMetrics are integer-valued metrics (counts of flights, landings, etc.).
var ErrFieldTooLong = errors.New("field exceeds maximum length")
ErrFieldTooLong is returned when a text field exceeds its maximum allowed length.
var ErrInvalidFlightBaseline = errors.New("invalid flight baseline")
ErrInvalidFlightBaseline indicates a baseline failed validation.
var TimeMetrics = map[string]bool{ "total_time": true, "pic_time": true, "dual_time": true, "night_time": true, "ifr_time": true, "cross_country_time": true, }
TimeMetrics are metrics measured in minutes in the database and expressed to the user in hours by default. Membership also drives Unit handling.
var ValidApproachTypes = map[string]bool{ "ILS": true, "LOC": true, "VOR": true, "RNAV/GPS": true, "NDB": true, "LDA": true, "SDF": true, "PAR": true, "ASR": true, "Visual": true, "Circling": true, "Other": true, "Unknown": true, }
ValidApproachTypes lists all valid approach type values
var ValidFilterFields = map[string]map[string]bool{ "aircraft_class": {"eq": true, "in": true}, "aircraft_type": {"eq": true, "in": true}, "aircraft_registration": {"eq": true, "in": true}, "launch_method": {"eq": true, "in": true}, "aircraft_complex": {"is_true": true}, "aircraft_high_performance": {"is_true": true}, "aircraft_tailwheel": {"is_true": true}, "is_pic": {"is_true": true}, "is_dual": {"is_true": true}, "has_night": {"is_true": true}, "has_ifr": {"is_true": true}, "is_cross_country": {"is_true": true}, }
ValidFilterFields enumerates the fields a filter may reference, mapped to the operators each supports. "value"/"values" fields use eq/in; boolean/derived fields use is_true.
var ValidWindowUnits = map[string]bool{ "days": true, "weeks": true, "months": true, "years": true, }
ValidWindowUnits enumerates the accepted lookback units.
Functions ¶
func ContainsControlChar ¶ added in v1.3.1
ContainsControlChar reports whether s contains any control character (C0/C1, including CR, LF, NUL and tab). User-facing rule text must not: rejecting it at the input boundary stops email-header/log injection and stray control bytes reaching any downstream sink, independent of per-sink escaping.
func IsTimeMetric ¶ added in v1.3.1
IsTimeMetric reports whether a metric is measured in time (minutes).
func IsValidClassType ¶
IsValidClassType checks if a class type is valid
func IsValidCrewRole ¶
IsValidCrewRole checks if a crew role is valid
func IsValidMetric ¶ added in v1.3.1
IsValidMetric reports whether a metric is part of the controlled vocabulary.
func ValidateAircraftTextFields ¶
ValidateAircraftTextFields validates all text field lengths on an Aircraft.
func ValidateContactTextFields ¶
ValidateContactTextFields validates all text field lengths on a Contact.
func ValidateCredentialTextFields ¶
func ValidateCredentialTextFields(cr *Credential) error
ValidateCredentialTextFields validates all text field lengths on a Credential.
func ValidateFlightTextFields ¶
ValidateFlightTextFields validates all text field lengths on a Flight.
func ValidateLicenseTextFields ¶
ValidateLicenseTextFields validates all text field lengths on a License.
func ValidateOptionalStringLength ¶
ValidateOptionalStringLength checks an optional string field.
func ValidateStringLength ¶
ValidateStringLength checks that a string field does not exceed the given max length.
Types ¶
type Aircraft ¶
type Aircraft struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"userId"`
Registration string `json:"registration"`
Type string `json:"type"`
Make string `json:"make"`
Model string `json:"model"`
IsComplex bool `json:"isComplex"`
IsHighPerformance bool `json:"isHighPerformance"`
IsTailwheel bool `json:"isTailwheel"`
Notes *string `json:"notes,omitempty"`
IsActive bool `json:"isActive"`
AircraftClass *string `json:"aircraftClass,omitempty"`
// Logging defaults, prefilled when a flight with this aircraft is logged
DefaultDepartureICAO *string `json:"defaultDepartureIcao,omitempty"`
DefaultArrivalICAO *string `json:"defaultArrivalIcao,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
Aircraft represents an aircraft in a user's fleet
type AircraftRecencyRow ¶ added in v1.3.1
type AircraftRecencyRow struct {
Registration string
AircraftType string
Date time.Time
Landings int
}
AircraftRecencyRow is one day of landings for one registration/type pair, used to derive 90-day recency counts and lapse dates
type AircraftStats ¶ added in v1.3.1
type AircraftStats struct {
Registration string `json:"registration"`
TotalFlights int `json:"totalFlights"`
TotalMinutes int `json:"totalMinutes"`
LandingsDay int `json:"landingsDay"`
LandingsNight int `json:"landingsNight"`
FirstFlightDate *time.Time `json:"firstFlightDate,omitempty"`
LastFlightDate *time.Time `json:"lastFlightDate,omitempty"`
// Informational 90-day recency (EASA FCL.060(b)-style day recency:
// 3 landings in the preceding 90 days)
LandingsLast90Days int `json:"landingsLast90Days"`
RecencyLapsesOn *time.Time `json:"recencyLapsesOn,omitempty"`
}
AircraftStats holds flight statistics aggregated per aircraft registration
type AircraftTypeStats ¶ added in v1.3.1
type AircraftTypeStats struct {
AircraftType string `json:"aircraftType"`
TotalFlights int `json:"totalFlights"`
TotalMinutes int `json:"totalMinutes"`
LandingsDay int `json:"landingsDay"`
LandingsNight int `json:"landingsNight"`
FirstFlightDate *time.Time `json:"firstFlightDate,omitempty"`
LastFlightDate *time.Time `json:"lastFlightDate,omitempty"`
LandingsLast90Days int `json:"landingsLast90Days"`
RecencyLapsesOn *time.Time `json:"recencyLapsesOn,omitempty"`
}
AircraftTypeStats holds flight statistics aggregated per aircraft type
type ApproachEntry ¶
type ApproachEntry struct {
Type string `json:"type"`
Airport *string `json:"airport,omitempty"`
Runway *string `json:"runway,omitempty"`
}
ApproachEntry represents a single instrument approach with type and location
type BackupDestination ¶ added in v1.2.4
type BackupDestination struct {
ID uuid.UUID
UserID uuid.UUID
Provider string
DisplayName string
Config map[string]any
CredentialHint string
CredentialsEnc []byte
CredentialsNonce []byte
Schedule BackupSchedule
ScheduleHourUTC int
ScheduleDayOfWeek *int
ScheduleDayOfMonth *int
RetentionCount int
Status BackupDestinationStatus
LastError string
Enabled bool
ConsecutiveFailures int
LastRunAt *time.Time
LastSuccessAt *time.Time
LastSuccessSHA256 string
CreatedAt time.Time
UpdatedAt time.Time
}
BackupDestination is a user-owned cloud-storage target where NinerLog will upload JSON backups. Each destination is bound to one provider plugin (e.g. "s3") and carries provider-specific non-secret config in Config plus an encrypted credential blob.
type BackupDestinationStatus ¶ added in v1.2.4
type BackupDestinationStatus string
BackupDestinationStatus is the operational state of a destination.
const ( BackupStatusActive BackupDestinationStatus = "active" BackupStatusPaused BackupDestinationStatus = "paused" BackupStatusError BackupDestinationStatus = "error" )
func (BackupDestinationStatus) IsValid ¶ added in v1.2.4
func (s BackupDestinationStatus) IsValid() bool
IsValid reports whether the status is a known value.
type BackupRun ¶ added in v1.2.4
type BackupRun struct {
ID uuid.UUID
DestinationID uuid.UUID
UserID uuid.UUID
Status BackupRunStatus
Trigger BackupRunTrigger
StartedAt time.Time
CompletedAt *time.Time
DurationMs *int
SizeBytes *int64
SHA256 string
FlightCount *int
AircraftCount *int
LicenseCount *int
CredentialCount *int
RemotePath string
ErrorMessage string
CreatedAt time.Time
}
BackupRun is the audit record of a single backup attempt.
type BackupRunStatus ¶ added in v1.2.4
type BackupRunStatus string
BackupRunStatus is the outcome of a single backup run.
const ( BackupRunStatusSuccess BackupRunStatus = "success" BackupRunStatusFailed BackupRunStatus = "failed" BackupRunStatusSkipped BackupRunStatus = "skipped" )
type BackupRunTrigger ¶ added in v1.2.4
type BackupRunTrigger string
BackupRunTrigger captures whether a run was scheduled or user-triggered.
const ( BackupRunTriggerScheduled BackupRunTrigger = "scheduled" BackupRunTriggerManual BackupRunTrigger = "manual" )
type BackupSchedule ¶ added in v1.2.4
type BackupSchedule string
BackupSchedule controls how often the scheduler runs a destination.
const ( BackupScheduleManual BackupSchedule = "manual" BackupScheduleDaily BackupSchedule = "daily" BackupScheduleWeekly BackupSchedule = "weekly" BackupScheduleMonthly BackupSchedule = "monthly" )
func (BackupSchedule) IsValid ¶ added in v1.2.4
func (s BackupSchedule) IsValid() bool
IsValid reports whether the schedule is a known value.
type ClassRating ¶
type ClassRating struct {
ID uuid.UUID `json:"id"`
LicenseID uuid.UUID `json:"licenseId"`
ClassType ClassType `json:"classType"`
IssueDate time.Time `json:"issueDate"`
ExpiryDate *time.Time `json:"expiryDate,omitempty"`
Notes *string `json:"notes,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
ClassRating represents a class rating attached to a license
func (*ClassRating) IsExpired ¶
func (cr *ClassRating) IsExpired() bool
IsExpired checks if the class rating has expired
func (*ClassRating) IsExpiringSoon ¶
func (cr *ClassRating) IsExpiringSoon(days int) bool
IsExpiringSoon checks if the class rating expires within N days
type ClassType ¶
type ClassType string
ClassType represents the type of class rating
const ( ClassTypeSEPLand ClassType = "SEP_LAND" ClassTypeSEPSea ClassType = "SEP_SEA" ClassTypeMEPLand ClassType = "MEP_LAND" ClassTypeMEPSea ClassType = "MEP_SEA" ClassTypeSETLand ClassType = "SET_LAND" ClassTypeSETSea ClassType = "SET_SEA" ClassTypeTMG ClassType = "TMG" ClassTypeIR ClassType = "IR" ClassTypeOther ClassType = "OTHER" )
func ValidClassTypes ¶
func ValidClassTypes() []ClassType
ValidClassTypes returns all valid class types
type Contact ¶
type Contact struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"userId"`
Name string `json:"name"`
Email *string `json:"email,omitempty"`
Phone *string `json:"phone,omitempty"`
Notes *string `json:"notes,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
Contact represents a reusable person that a user can reference across flights
type Credential ¶
type Credential struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"userId"`
CredentialType CredentialType `json:"credentialType"`
CredentialNumber *string `json:"credentialNumber,omitempty"`
IssueDate time.Time `json:"issueDate"`
ExpiryDate *time.Time `json:"expiryDate,omitempty"`
IssuingAuthority string `json:"issuingAuthority"`
Notes *string `json:"notes,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
Credential represents a pilot credential (medical, language proficiency, security clearance)
func (*Credential) IsExpired ¶
func (c *Credential) IsExpired() bool
IsExpired checks if the credential has expired
func (*Credential) IsExpiringSoon ¶
func (c *Credential) IsExpiringSoon(days int) bool
IsExpiringSoon checks if the credential expires within the given number of days
type CredentialType ¶
type CredentialType string
const ( CredentialTypeEASAClass1Medical CredentialType = "EASA_CLASS1_MEDICAL" CredentialTypeEASAClass2Medical CredentialType = "EASA_CLASS2_MEDICAL" CredentialTypeEASALAPLMedical CredentialType = "EASA_LAPL_MEDICAL" CredentialTypeFAAClass1Medical CredentialType = "FAA_CLASS1_MEDICAL" CredentialTypeFAAClass2Medical CredentialType = "FAA_CLASS2_MEDICAL" CredentialTypeFAAClass3Medical CredentialType = "FAA_CLASS3_MEDICAL" CredentialTypeLangICAOLevel4 CredentialType = "LANG_ICAO_LEVEL4" CredentialTypeLangICAOLevel5 CredentialType = "LANG_ICAO_LEVEL5" CredentialTypeLangICAOLevel6 CredentialType = "LANG_ICAO_LEVEL6" CredentialTypeSecClearanceZUP CredentialType = "SEC_CLEARANCE_ZUP" CredentialTypeSecClearanceZUBB CredentialType = "SEC_CLEARANCE_ZUBB" CredentialTypeOther CredentialType = "OTHER" )
#nosec G101 -- enum identifiers describe credential types, not secrets.
type CurrencyData ¶
CurrencyData holds landing/flight counts for currency calculation
type CurrencyFilter ¶ added in v1.3.1
type CurrencyFilter struct {
Field string `json:"field"`
Op string `json:"op"`
Value string `json:"value,omitempty"`
Values []string `json:"values,omitempty"`
}
CurrencyFilter narrows the set of flights a rule counts. Op determines how Value/Values are interpreted:
- "eq": the flight's field equals Value
- "in": the flight's field is one of Values
- "is_true": the (boolean/derived) field is true; Value/Values ignored
type CurrencyRequirement ¶ added in v1.3.1
type CurrencyRequirement struct {
Metric string `json:"metric"`
Min float64 `json:"min"`
Unit string `json:"unit,omitempty"` // hours | minutes (time metrics only)
Label string `json:"label,omitempty"`
}
CurrencyRequirement is a single "at least N" threshold on an aggregated metric over the filtered, windowed flight set. For time metrics, Unit selects how Min is expressed (hours or minutes); count metrics ignore Unit.
type CurrencyWindow ¶ added in v1.3.1
type CurrencyWindow struct {
Amount int `json:"amount"`
Unit string `json:"unit"` // days | weeks | months | years
}
CurrencyWindow is a rolling lookback anchored at the moment of evaluation: only flights on or after (now − Amount×Unit) count. Expiry-anchored windows (as used by some regulatory revalidation rules) are intentionally out of scope for user-authored rules in this version.
type CustomCurrencyRule ¶ added in v1.3.1
type CustomCurrencyRule struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"userId"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
Emoji *string `json:"emoji,omitempty"`
Definition CustomCurrencyRuleBody `json:"definition"`
// Enabled is false when the rule is paused: it is kept and listed but not
// evaluated or surfaced as active currency.
Enabled bool `json:"enabled"`
// Notify opts this rule into expiry/lapse email notifications (per-rule).
Notify bool `json:"notify"`
ImportedFrom *uuid.UUID `json:"importedFrom,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
CustomCurrencyRule is a user-authored, modular currency definition. The rule body (window + filters + requirements) lives in Definition and is evaluated against the user's flights by the currency engine. Rules are private by default; enabling sharing exposes a read-only copy via ShareToken that other users can import.
type CustomCurrencyRuleBody ¶ added in v1.3.1
type CustomCurrencyRuleBody struct {
Window CurrencyWindow `json:"window"`
Filters []CurrencyFilter `json:"filters,omitempty"`
Requirements []CurrencyRequirement `json:"requirements"`
}
CustomCurrencyRuleBody is the declarative rule document. It mirrors the shape of the built-in engine's rules: a lookback Window, a set of Filters that select which flights count, and one or more Requirements measured against aggregated flight metrics. Requirements are combined with logical AND — the rule is "current" only when every requirement is met.
func (*CustomCurrencyRuleBody) Scan ¶ added in v1.3.1
func (b *CustomCurrencyRuleBody) Scan(src interface{}) error
Scan implements sql.Scanner so the body can be read from a JSONB column.
func (*CustomCurrencyRuleBody) Validate ¶ added in v1.3.1
func (b *CustomCurrencyRuleBody) Validate() error
Validate checks a rule body against the controlled vocabulary and structural limits. It returns a descriptive error suitable for surfacing to the author.
type EmailVerificationToken ¶ added in v1.2.5
type EmailVerificationToken struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"user_id"`
TokenHash string `json:"-"`
ExpiresAt time.Time `json:"expires_at"`
Used bool `json:"used"`
CreatedAt time.Time `json:"created_at"`
}
EmailVerificationToken represents a single-use email-verification token sent to a user after registration (or via the resend endpoint).
type Flight ¶
type Flight struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"userId"`
Date time.Time `json:"date"`
// Aircraft information
AircraftReg string `json:"aircraftReg"`
AircraftType string `json:"aircraftType"`
// Route information
DepartureICAO *string `json:"departureIcao,omitempty"`
ArrivalICAO *string `json:"arrivalIcao,omitempty"`
OffBlockTime *string `json:"offBlockTime,omitempty"` // HH:MM:SS format - chocks off / engine start (UTC)
OnBlockTime *string `json:"onBlockTime,omitempty"` // HH:MM:SS format - chocks on / engine shutdown (UTC)
DepartureTime *string `json:"departureTime,omitempty"` // HH:MM:SS format - takeoff time (UTC)
ArrivalTime *string `json:"arrivalTime,omitempty"` // HH:MM:SS format - landing time (UTC)
// Flight times (in minutes)
TotalTime int `json:"totalTime"`
IsPIC bool `json:"isPic"`
IsDual bool `json:"isDual"`
PICTime int `json:"picTime"`
DualTime int `json:"dualTime"`
NightTime int `json:"nightTime"`
IFRTime int `json:"ifrTime"`
// Landings
LandingsDay int `json:"landingsDay"`
LandingsNight int `json:"landingsNight"`
AllLandings int `json:"allLandings"` // Auto-calculated: day + night
// Takeoffs
TakeoffsDay int `json:"takeoffsDay"` // Auto-calculated from sunset/sunrise at departure (with manual override)
TakeoffsNight int `json:"takeoffsNight"` // Auto-calculated from sunset/sunrise at departure (with manual override)
// Route
Route *string `json:"route,omitempty"` // Comma-separated ICAO waypoints
// Auto-calculated fields
SoloTime int `json:"soloTime"` // Auto-calculated when not dual and not PIC with crew
CrossCountryTime int `json:"crossCountryTime"` // Auto-calculated when departure ≠ arrival
Distance float64 `json:"distance"` // Auto-calculated from airport coordinates (NM)
// Manual override flags
TakeoffsDayOverride bool `json:"-"` // When true, takeoffsDay is not auto-calculated
TakeoffsNightOverride bool `json:"-"` // When true, takeoffsNight is not auto-calculated
LandingsDayOverride bool `json:"-"` // When true, landingsDay is not auto-calculated
LandingsNightOverride bool `json:"-"` // When true, landingsNight is not auto-calculated
// Instructor & comments
InstructorName *string `json:"instructorName,omitempty"`
InstructorComments *string `json:"instructorComments,omitempty"`
// PIC name (EASA AMC1 FCL.050 Col 12)
PICName *string `json:"picName,omitempty"`
// Multi-crew / advanced times
SICTime int `json:"sicTime"`
DualGivenTime int `json:"dualGivenTime"`
SimulatedFlightTime int `json:"simulatedFlightTime"`
GroundTrainingTime int `json:"groundTrainingTime"`
MultiPilotTime int `json:"multiPilotTime"` // EASA AMC1 FCL.050 Col 10
// FSTD type designation (EASA AMC1 FCL.050 Col 22, FAA §61.51(b)(1)(iv))
FSTDType *string `json:"fstdType,omitempty"`
// Instrument tracking
ActualInstrumentTime int `json:"actualInstrumentTime"`
SimulatedInstrumentTime int `json:"simulatedInstrumentTime"`
Holds int `json:"holds"`
ApproachesCount int `json:"approachesCount"`
Approaches []ApproachEntry `json:"approaches,omitempty"` // Structured approach data (FAA §61.51(g)(3))
IsIPC bool `json:"isIpc"`
IsFlightReview bool `json:"isFlightReview"`
IsProficiencyCheck bool `json:"isProficiencyCheck"`
// Endorsements (EASA AMC1 FCL.050 Col 24, FAA §61.51(h))
Endorsements *string `json:"endorsements,omitempty"`
// SPL / Glider
LaunchMethod *string `json:"launchMethod,omitempty"` // winch, aerotow, self-launch
// Crew members on board (populated from flight_crew_members table)
CrewMembers []FlightCrewMember `json:"crewMembers,omitempty"`
// Additional information
Remarks *string `json:"remarks,omitempty"`
// Instructor sign-off lock. Non-nil iff the flight is locked by a
// completed, non-voided FlightSignature (see flight_signature.go).
SignatureID *uuid.UUID `json:"signatureId,omitempty"`
// Metadata
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
Flight represents a flight log entry
func (*Flight) ValidateTimeDistribution ¶
ValidateTimeDistribution checks if time distribution is valid
type FlightBaseline ¶ added in v1.2.3
type FlightBaseline struct {
UserID uuid.UUID
BaselineDate time.Time
TotalFlights int
TotalMinutes int
PICMinutes int
SICMinutes int
DualMinutes int
DualGivenMinutes int
MultiPilotMinutes int
NightMinutes int
IFRMinutes int
SoloMinutes int
CrossCountryMinutes int
LandingsDay int
LandingsNight int
Notes *string
CreatedAt time.Time
UpdatedAt time.Time
}
FlightBaseline represents a per-user "initial hours snapshot": a carried-forward total of pre-existing flying experience that is added on top of logged flights when computing aggregated user-level statistics.
func (*FlightBaseline) Validate ¶ added in v1.2.3
func (b *FlightBaseline) Validate() error
Validate enforces the basic invariants that aren't covered by DB CHECK constraints (non-negative values are enforced in the database, but we still fail fast at the API boundary).
type FlightCrewMember ¶
type FlightCrewMember struct {
ID uuid.UUID `json:"id"`
FlightID uuid.UUID `json:"flightId"`
ContactID *uuid.UUID `json:"contactId,omitempty"`
Name string `json:"name"`
Role CrewRole `json:"role"`
}
FlightCrewMember represents a person on board a specific flight
type FlightSession ¶ added in v1.2.8
type FlightSession struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"userId"`
Status string `json:"status"` // open | completed | discarded
AircraftReg *string `json:"aircraftReg,omitempty"`
DepartureICAO *string `json:"departureIcao,omitempty"`
ArrivalICAO *string `json:"arrivalIcao,omitempty"`
OffBlockAt *time.Time `json:"offBlockAt,omitempty"`
TakeoffAt *time.Time `json:"takeoffAt,omitempty"`
LandingAt *time.Time `json:"landingAt,omitempty"`
OnBlockAt *time.Time `json:"onBlockAt,omitempty"`
// FlightID is set once the session has been completed and converted
// into a regular flight log entry.
FlightID *uuid.UUID `json:"flightId,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
FlightSession represents an in-progress flight captured live via tap-to-log from a mobile device. Event instants are full UTC timestamps (not bare times of day) so flights crossing midnight stay unambiguous; they are split into date + HH:MM:SS when the session is converted into a Flight.
func (*FlightSession) BlockDuration ¶ added in v1.2.8
func (s *FlightSession) BlockDuration() time.Duration
BlockDuration returns the off-block → on-block duration, or 0 when either instant is missing.
func (*FlightSession) ValidateEventOrder ¶ added in v1.2.8
func (s *FlightSession) ValidateEventOrder() error
ValidateEventOrder checks that whichever event instants are present occur in the physical order off block ≤ takeoff ≤ landing ≤ on block.
type FlightSignature ¶ added in v1.2.9
type FlightSignature struct {
ID uuid.UUID
FlightID uuid.UUID
UserID uuid.UUID
Method SignatureMethod
Status SignatureStatus
// Deferred token fields; nil for SignatureMethodLive.
TokenHash *string
TokenExpiresAt *time.Time
InstructorEmail *string
EmailSentAt *time.Time
EmailSendCount int
ContactID *uuid.UUID
// Captured at completion time.
InstructorName *string
InstructorCredentialNo *string
SignatureImage []byte
SignedAt *time.Time
SignerIP *string
SignerUserAgent *string
VoidedAt *time.Time
VoidedReason *string
CreatedAt time.Time
UpdatedAt time.Time
}
FlightSignature is an instructor sign-off request/record for a single flight log entry. See db/migrations/000042_create_flight_signatures for the full column rationale.
type FlightStatistics ¶
type FlightStatistics struct {
TotalFlights int
TotalMinutes int
PICMinutes int
DualMinutes int
NightMinutes int
IFRMinutes int
SoloMinutes int
CrossCountryMinutes int
LandingsDay int
LandingsNight int
SICMinutes int
DualGivenMinutes int
}
FlightStatistics holds aggregated flight statistics for a license
type License ¶
type License struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"userId"`
RegulatoryAuthority string `json:"regulatoryAuthority" binding:"required"`
LicenseType string `json:"licenseType" binding:"required"`
LicenseNumber string `json:"licenseNumber" binding:"required"`
IssueDate time.Time `json:"issueDate" binding:"required"`
IssuingAuthority string `json:"issuingAuthority" binding:"required"`
RequiresSeparateLogbook bool `json:"requiresSeparateLogbook"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
License represents a pilot license
type NotificationCategory ¶
type NotificationCategory string
NotificationCategory represents a granular notification category
const ( NotifCategoryCredentialMedical NotificationCategory = "credential_medical" NotifCategoryCredentialLanguage NotificationCategory = "credential_language" NotifCategoryCredentialSecurity NotificationCategory = "credential_security" NotifCategoryCredentialOther NotificationCategory = "credential_other" NotifCategoryRatingExpiry NotificationCategory = "rating_expiry" NotifCategoryCurrencyPassenger NotificationCategory = "currency_passenger" NotifCategoryCurrencyNight NotificationCategory = "currency_night" NotifCategoryCurrencyInstrument NotificationCategory = "currency_instrument" NotifCategoryCurrencyFlightReview NotificationCategory = "currency_flight_review" NotifCategoryCurrencyRevalidation NotificationCategory = "currency_revalidation" // NotifCategoryCustomCurrency labels notifications for user-authored custom // currency rules. It is used as the log/dedup type; opt-in is per-rule // (custom_currency_rules.notify) rather than via enabled_categories. NotifCategoryCustomCurrency NotificationCategory = "currency_custom" )
#nosec G101 -- notification category identifiers describe credential reminders, not secrets.
func CredentialCategoryForType ¶
func CredentialCategoryForType(credType CredentialType) NotificationCategory
CredentialCategoryForType maps a credential type to a notification category
type NotificationLog ¶
type NotificationLog struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"userId"`
NotificationType string `json:"notificationType"`
ReferenceID *uuid.UUID `json:"referenceId,omitempty"`
ReferenceType *string `json:"referenceType,omitempty"`
DaysBeforeExpiry *int `json:"daysBeforeExpiry,omitempty"`
ExpiryReferenceDate *time.Time `json:"expiryReferenceDate,omitempty"`
Subject *string `json:"subject,omitempty"`
SentAt time.Time `json:"sentAt"`
}
NotificationLog tracks sent notifications to avoid duplicates
type NotificationPreferences ¶
type NotificationPreferences struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"userId"`
EmailEnabled bool `json:"emailEnabled"`
EnabledCategories pq.StringArray `json:"enabledCategories"`
WarningDays pq.Int64Array `json:"warningDays"`
CheckHour int `json:"checkHour"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
NotificationPreferences holds a user's notification settings
func (*NotificationPreferences) IsCategoryEnabled ¶
func (p *NotificationPreferences) IsCategoryEnabled(category NotificationCategory) bool
IsCategoryEnabled checks if a specific notification category is enabled
type PasswordResetToken ¶
type PasswordResetToken struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"user_id"`
TokenHash string `json:"-"`
ExpiresAt time.Time `json:"expires_at"`
Used bool `json:"used"`
CreatedAt time.Time `json:"created_at"`
}
PasswordResetToken represents a password reset token
type RefreshToken ¶
type RefreshToken struct {
ID uuid.UUID `json:"id"`
UserID uuid.UUID `json:"user_id"`
TokenHash string `json:"-"`
ExpiresAt time.Time `json:"expires_at"`
Revoked bool `json:"revoked"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
RefreshToken represents a refresh token in the system
type SignatureMethod ¶ added in v1.2.9
type SignatureMethod string
SignatureMethod describes how a FlightSignature was (or will be) captured.
const ( // SignatureMethodLive is captured in person on the flight owner's own // device while the instructor is physically present. Completes // synchronously; no token involved. SignatureMethodLive SignatureMethod = "live" // SignatureMethodDeferred is a token-based flow: the owner creates a // request, and the instructor completes it later via the public // /sign/{token} link, delivered by email and/or a shareable link/QR. SignatureMethodDeferred SignatureMethod = "deferred" )
type SignatureStatus ¶ added in v1.2.9
type SignatureStatus string
SignatureStatus is the lifecycle state of a FlightSignature row.
const ( // SignatureStatusPending is a deferred request awaiting completion. SignatureStatusPending SignatureStatus = "pending" // SignatureStatusCompleted means the signature was captured and (for // deferred flows) the token has been consumed. The flight is locked. SignatureStatusCompleted SignatureStatus = "completed" // SignatureStatusRevoked means the owner cancelled a pending request // before anyone signed it. SignatureStatusRevoked SignatureStatus = "revoked" // SignatureStatusVoided means a completed signature was later // invalidated by the owner (with a reason), unlocking the flight again. SignatureStatusVoided SignatureStatus = "voided" // SignatureStatusExpired means a pending request's token lapsed before // anyone signed it. SignatureStatusExpired SignatureStatus = "expired" )
type User ¶
type User struct {
ID uuid.UUID `json:"id"`
Email string `json:"email"`
PasswordHash string `json:"-"`
Name string `json:"name"`
EmailVerified bool `json:"emailVerified"`
TwoFactorEnabled bool `json:"twoFactorEnabled"`
TwoFactorSecret *string `json:"-"` // never exposed in JSON
RecoveryCodes pq.StringArray `json:"-"` // never exposed in JSON
FailedLoginAttempts int `json:"-"`
LockedUntil *time.Time `json:"-"`
Disabled bool `json:"disabled"`
LastLoginAt *time.Time `json:"lastLoginAt,omitempty"`
TimeDisplayFormat string `json:"timeDisplayFormat"`
DateFormat string `json:"dateFormat"`
DecimalSeparator string `json:"decimalSeparator"`
PreferredLocale string `json:"preferredLocale"`
// Informational 90-day recency indicator preferences (FCL.060(b)-style)
RecencyPerModel bool `json:"recencyPerModel"`
RecencyPerRegistration bool `json:"recencyPerRegistration"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
User represents a user in the system
type WebAuthnCredential ¶ added in v1.2.0
type WebAuthnCredential struct {
ID uuid.UUID
UserID uuid.UUID
CredentialID []byte // raw credential id from the authenticator
PublicKey []byte // CBOR-encoded COSE public key
AttestationType string
AAGUID []byte
SignCount uint32
Transports pq.StringArray
Label *string
UserPresent bool
UserVerified bool
BackupEligible bool
BackupState bool
CreatedAt time.Time
LastUsedAt *time.Time
}
WebAuthnCredential represents a passkey / WebAuthn credential registered by a user.
type WebAuthnSession ¶ added in v1.2.0
type WebAuthnSession struct {
ID uuid.UUID
UserID *uuid.UUID // nil for usernameless / discoverable login
Challenge string
SessionData []byte // serialized webauthn.SessionData
Purpose string // "registration" | "login"
ExpiresAt time.Time
CreatedAt time.Time
}
WebAuthnSession holds the transient state of an in-flight WebAuthn ceremony (registration or authentication) until the client returns its assertion.