Documentation
¶
Index ¶
- Constants
- Variables
- func ProviderHealthStaleAfter(provider string) time.Duration
- func ProviderHealthStatus(provider ProviderHealth, now time.Time, staleAfter time.Duration) string
- func ProviderStatusOrder(statuses []ArtistProviderStatus)
- type AdminArtist
- type AdminDeliveryHistory
- type AdminDestinationHealth
- type AdminUser
- type Artist
- type ArtistBreakdown
- type ArtistCoverage
- type ArtistProviderStatus
- type ArtistResolution
- type AssuranceSummary
- type CalendarRelease
- type CoverageSummary
- type Delivery
- type DeliveryHistory
- type Destination
- type DestinationHealth
- type DiagnosticsProvider
- type DiagnosticsSnapshot
- type DigestDelivery
- type EvidenceIssue
- type FollowNotificationRule
- type ITunesArtworkArtist
- type ImportInput
- type ImportJob
- type ImportRow
- type ListenBrainzStats
- type MaintenanceStats
- type ManualSyncRequest
- type NotificationHold
- type NotificationPreferences
- type ProviderHealth
- type Release
- type ReleaseBatch
- type ReleaseCredit
- type ReleaseDetail
- type ReleaseEvidence
- type ReleaseInboxItem
- type ReleaseObservation
- type ReleaseTimelineEntry
- type ReleaseTruthDecision
- type ResolutionCandidate
- type Session
- type SpotifyPollingState
- type Store
- func (s *Store) AddDestination(ctx context.Context, userID int64, name, service string, encrypted []byte) error
- func (s *Store) AdminArtists(ctx context.Context) ([]AdminArtist, error)
- func (s *Store) AdminDeliveryDetail(ctx context.Context, deliveryID int64) (AdminDeliveryHistory, error)
- func (s *Store) AdminDeliveryHistory(ctx context.Context, limit, offset int) ([]AdminDeliveryHistory, error)
- func (s *Store) AdminDeliveryHistoryCount(ctx context.Context) (int, error)
- func (s *Store) AdminDeliveryHistorySummary(ctx context.Context, limit, offset int) ([]AdminDeliveryHistory, error)
- func (s *Store) AdminDestinationHealth(ctx context.Context) ([]AdminDestinationHealth, error)
- func (s *Store) AdminUsers(ctx context.Context) ([]AdminUser, error)
- func (s *Store) ApplicationLogs(ctx context.Context, limit int) ([]logging.Entry, error)
- func (s *Store) ApplyITunesArtworkBackfill(ctx context.Context, artistID int64, releases []Release, observed time.Time) (checked, updated int, err error)
- func (s *Store) ApplyReleaseBatches(ctx context.Context, artist Artist, batches []ReleaseBatch, observed time.Time) error
- func (s *Store) ApplyReleaseSync(ctx context.Context, artist Artist, releases []Release, observed time.Time) error
- func (s *Store) ArtistByID(ctx context.Context, id int64) (Artist, error)
- func (s *Store) ArtistByMBID(ctx context.Context, mbid string) (Artist, error)
- func (s *Store) ArtistGenres(ctx context.Context, artistID int64) ([]string, error)
- func (s *Store) ArtistResolution(ctx context.Context, userID, resolutionID int64) (ArtistResolution, error)
- func (s *Store) ArtistResolutions(ctx context.Context, userID int64) ([]ArtistResolution, error)
- func (s *Store) ArtistsDue(ctx context.Context, now time.Time, limit int) ([]Artist, error)
- func (s *Store) CalendarReleases(ctx context.Context, userID int64, from, to string, limit int) ([]CalendarRelease, error)
- func (s *Store) CancelArtistResolution(ctx context.Context, userID, resolutionID int64) error
- func (s *Store) ClaimManualSyncRequests(ctx context.Context, limit int) ([]ManualSyncRequest, error)
- func (s *Store) ClearLoginFailures(ctx context.Context, key string)
- func (s *Store) ClearReleaseTruthDecision(ctx context.Context, userID, releaseID int64) error
- func (s *Store) Close() error
- func (s *Store) CompleteArtistResolution(ctx context.Context, resolution ArtistResolution, artist Artist) (Artist, bool, error)
- func (s *Store) CompleteManualSyncRequest(ctx context.Context, id int64, syncErr error) error
- func (s *Store) ConsumeAuthToken(ctx context.Context, raw, kind string) (email string, userID *int64, err error)
- func (s *Store) CoverageOverview(ctx context.Context, userID int64, limit int) (CoverageSummary, AssuranceSummary, error)
- func (s *Store) CoverageSummary(ctx context.Context, userID int64) (CoverageSummary, error)
- func (s *Store) CreateArtistResolution(ctx context.Context, userID int64, ...) (ArtistResolution, bool, error)
- func (s *Store) CreateAuthToken(ctx context.Context, kind, email string, userID *int64, creator int64, ...) (string, error)
- func (s *Store) CreateImportJob(ctx context.Context, userID int64) (ImportJob, error)
- func (s *Store) CreateManualSyncRequest(ctx context.Context, userID int64, scope string, artistID *int64) (ManualSyncRequest, error)
- func (s *Store) CreateSession(ctx context.Context, userID int64, ttl time.Duration) (raw, csrf string, err error)
- func (s *Store) CreateUser(ctx context.Context, email, hash, role, timezone, username string) (int64, error)
- func (s *Store) CreateUserFromInvite(ctx context.Context, raw, hash, username, timezone string) error
- func (s *Store) DashboardReleases(ctx context.Context, userID int64, today string, limit int) (upcoming []Release, recent []Release, err error)
- func (s *Store) DeleteDestination(ctx context.Context, userID, id int64) error
- func (s *Store) DeleteSession(ctx context.Context, raw string) error
- func (s *Store) DeleteUser(ctx context.Context, actingAdminID, userID int64) error
- func (s *Store) DeliveryHistory(ctx context.Context, userID int64, limit int) ([]DeliveryHistory, error)
- func (s *Store) Destination(ctx context.Context, userID, id int64) (Destination, error)
- func (s *Store) DestinationHealthByUser(ctx context.Context, userID int64) (map[int64]DestinationHealth, error)
- func (s *Store) Destinations(ctx context.Context, userID int64) ([]Destination, error)
- func (s *Store) Diagnostics(ctx context.Context) (DiagnosticsSnapshot, error)
- func (s *Store) DueArtistResolutions(ctx context.Context, now time.Time, limit int) ([]ArtistResolution, error)
- func (s *Store) DueDeliveries(ctx context.Context, now time.Time, limit int) ([]Delivery, error)
- func (s *Store) DueDigestDeliveries(ctx context.Context, now time.Time, limit int) ([]DigestDelivery, error)
- func (s *Store) DueITunesArtworkArtist(ctx context.Context, now time.Time) (ITunesArtworkArtist, bool, error)
- func (s *Store) DueListenBrainzArtists(ctx context.Context, now time.Time, limit int) ([]Artist, error)
- func (s *Store) EnqueueEvent(ctx context.Context, userID, releaseID int64, eventType, title, body string, ...) error
- func (s *Store) EvidenceIssueCount(ctx context.Context, userID int64, status, state, issueType, severity string, ...) (int, error)
- func (s *Store) EvidenceIssueUnreadCount(ctx context.Context, userID int64, now time.Time) (int, error)
- func (s *Store) EvidenceIssues(ctx context.Context, userID int64, status, state, issueType, severity string, ...) ([]EvidenceIssue, error)
- func (s *Store) EvidenceIssuesForRelease(ctx context.Context, userID, releaseID int64, now time.Time) ([]EvidenceIssue, error)
- func (s *Store) FinishDeliveryAttempt(ctx context.Context, attemptID, destinationID int64, success bool, ...) error
- func (s *Store) Follow(ctx context.Context, userID, artistID int64) (bool, error)
- func (s *Store) FollowNotificationRule(ctx context.Context, userID, artistID int64) (FollowNotificationRule, error)
- func (s *Store) FollowNotificationRules(ctx context.Context, userID int64, artistIDs []int64) (map[int64]FollowNotificationRule, error)
- func (s *Store) FollowedArtistCount(ctx context.Context, userID int64) (int, error)
- func (s *Store) FollowedArtistCoveragePage(ctx context.Context, userID int64, limit, offset int) ([]ArtistCoverage, error)
- func (s *Store) FollowedArtists(ctx context.Context, userID int64) ([]Artist, error)
- func (s *Store) FollowedArtistsFiltered(ctx context.Context, userID int64, genre, country, artistType string) ([]Artist, error)
- func (s *Store) FollowedArtistsFilteredCount(ctx context.Context, userID int64, genre, country, artistType string) (int, error)
- func (s *Store) FollowedArtistsFilteredPage(ctx context.Context, userID int64, genre, country, artistType string, ...) ([]Artist, error)
- func (s *Store) FollowedBreakdown(ctx context.Context, userID int64, dimension string) ([]ArtistBreakdown, error)
- func (s *Store) Healthy(ctx context.Context) error
- func (s *Store) ImportJob(ctx context.Context, userID, jobID int64) (ImportJob, error)
- func (s *Store) InsertApplicationLog(ctx context.Context, entry logging.Entry) error
- func (s *Store) IsFollowing(ctx context.Context, userID, artistID int64) (bool, error)
- func (s *Store) LatestSpotifyReleaseDate(ctx context.Context, artistID int64) (string, error)
- func (s *Store) LoginAllowed(ctx context.Context, key string) (bool, error)
- func (s *Store) ManualSyncRequests(ctx context.Context, limit int) ([]ManualSyncRequest, error)
- func (s *Store) MarkAllArtistsDue(ctx context.Context) error
- func (s *Store) MarkArtistChecked(ctx context.Context, artistID int64, now time.Time, interval time.Duration) error
- func (s *Store) MarkArtistResolutionReview(ctx context.Context, userID, resolutionID int64, ...) error
- func (s *Store) MarkDeliveryFailed(ctx context.Context, id int64, attempts int, message string, now time.Time) error
- func (s *Store) MarkDeliverySent(ctx context.Context, id int64, now time.Time) error
- func (s *Store) MarkDigestDeliveryFailed(ctx context.Context, id int64, attempts int, message string, now time.Time) error
- func (s *Store) MarkDigestDeliverySent(ctx context.Context, id int64, now time.Time) error
- func (s *Store) MarkSpotifyChecked(ctx context.Context, artistID int64, now time.Time, interval time.Duration) error
- func (s *Store) MarkSpotifyCheckedAdaptive(ctx context.Context, artistID int64, now time.Time, interval time.Duration, ...) error
- func (s *Store) NotificationHolds(ctx context.Context, userID int64, limit int) ([]NotificationHold, error)
- func (s *Store) NotificationHoldsForRelease(ctx context.Context, userID, releaseID int64) ([]NotificationHold, error)
- func (s *Store) NotificationPreferences(ctx context.Context, userID int64) (NotificationPreferences, error)
- func (s *Store) PauseFollowNotificationRule(ctx context.Context, userID, artistID int64, until *time.Time) error
- func (s *Store) ProviderHealth(ctx context.Context) ([]ProviderHealth, error)
- func (s *Store) ProviderHealthByName(ctx context.Context, provider string) (ProviderHealth, error)
- func (s *Store) PruneApplicationLogs(ctx context.Context, before time.Time) error
- func (s *Store) PruneExpiredState(ctx context.Context, now time.Time) (MaintenanceStats, error)
- func (s *Store) QueueDueReleaseDays(ctx context.Context, now time.Time) error
- func (s *Store) QueueDueReleaseDigests(ctx context.Context, now time.Time) (int, error)
- func (s *Store) RecentReleases(ctx context.Context, userID int64, limit int) ([]Release, error)
- func (s *Store) RecordArtistProviderStatus(ctx context.Context, status ArtistProviderStatus) error
- func (s *Store) RecordLoginFailure(ctx context.Context, key string) error
- func (s *Store) ReleaseDetail(ctx context.Context, userID, releaseID int64) (ReleaseDetail, error)
- func (s *Store) ReleaseInbox(ctx context.Context, userID int64, state, source, primaryType string, ...) ([]ReleaseInboxItem, error)
- func (s *Store) ReleaseInboxCount(ctx context.Context, userID int64, state, source, primaryType string, ...) (int, error)
- func (s *Store) ReleaseInboxUnreadCount(ctx context.Context, userID int64, now time.Time) (int, error)
- func (s *Store) ReleaseTimeline(ctx context.Context, userID, releaseID int64) ([]ReleaseTimelineEntry, error)
- func (s *Store) RenameDestination(ctx context.Context, userID, destinationID int64, name string) error
- func (s *Store) ResetPasswordWithToken(ctx context.Context, raw, hash string) error
- func (s *Store) ResolveNotificationHold(ctx context.Context, userID, holdID int64, action string) error
- func (s *Store) RetryArtistResolution(ctx context.Context, userID, resolutionID int64, attempts int, next time.Time, ...) error
- func (s *Store) RetryFailedDeliveries(ctx context.Context, userID, destinationID int64, now time.Time) (int, error)
- func (s *Store) SaveArtistGenres(ctx context.Context, artistID int64, genres []string) error
- func (s *Store) SaveImportRow(ctx context.Context, userID, jobID int64, input ImportInput) (ImportRow, error)
- func (s *Store) SaveListenBrainzStats(ctx context.Context, stats map[int64]ListenBrainzStats, now, next time.Time) error
- func (s *Store) ScheduleArtistCheck(ctx context.Context, artistID int64, next time.Time) error
- func (s *Store) ScheduleITunesArtworkRetry(ctx context.Context, artistID int64, next time.Time) error
- func (s *Store) ScheduleListenBrainzRefresh(ctx context.Context, artistIDs []int64, next time.Time) error
- func (s *Store) ScheduleListenBrainzRetry(ctx context.Context, artistIDs []int64, next time.Time, message string) error
- func (s *Store) ScheduleSpotifyCheck(ctx context.Context, artistID int64, next time.Time) error
- func (s *Store) Session(ctx context.Context, raw string) (Session, error)
- func (s *Store) SetEvidenceIssueState(ctx context.Context, userID, issueID int64, state string, ...) error
- func (s *Store) SetFollowNotificationDeliveryMode(ctx context.Context, userID int64, artistIDs []int64, mode string) (int, error)
- func (s *Store) SetReleaseInboxState(ctx context.Context, userID, releaseID int64, state string, ...) error
- func (s *Store) SetReleaseTruthDecision(ctx context.Context, userID, releaseID int64, provider, reason string) error
- func (s *Store) SpotifyBatchChanged(ctx context.Context, releases []Release) (bool, error)
- func (s *Store) SpotifyPollingState(ctx context.Context, artistID int64) (SpotifyPollingState, error)
- func (s *Store) StartDeliveryAttempt(ctx context.Context, deliveryID, digestDeliveryID int64, ...) (int64, error)
- func (s *Store) TopListenBrainzArtists(ctx context.Context, userID int64, limit int) ([]Artist, error)
- func (s *Store) Unfollow(ctx context.Context, userID, artistID int64) error
- func (s *Store) UpdateFollowNotificationRule(ctx context.Context, userID, artistID int64, rule FollowNotificationRule) error
- func (s *Store) UpdateFollowNotificationRules(ctx context.Context, userID int64, artistIDs []int64, ...) (int, error)
- func (s *Store) UpdateNotificationPreferences(ctx context.Context, p NotificationPreferences) error
- func (s *Store) UpdatePassword(ctx context.Context, userID int64, hash string) error
- func (s *Store) UpdateProfile(ctx context.Context, userID int64, timezone, reminder, username string) error
- func (s *Store) UpsertArtist(ctx context.Context, a Artist) (Artist, error)
- func (s *Store) UpsertProviderHealth(ctx context.Context, provider string, success bool, next *time.Time, ...) error
- func (s *Store) UserByEmail(ctx context.Context, email string) (User, error)
- func (s *Store) UserByID(ctx context.Context, id int64) (User, error)
- func (s *Store) UserCount(ctx context.Context) (int, error)
- func (s *Store) ValidateDestinationCiphertexts(ctx context.Context, decrypt func([]byte) (string, error)) error
- func (s *Store) WatchlistAssurance(ctx context.Context, userID int64, limit int) (AssuranceSummary, error)
- type User
Constants ¶
const ( FollowDeliveryInherit = "inherit" FollowDeliveryImmediate = "immediate" FollowDeliveryDigest = "digest" FollowDeliveryOff = "off" )
Variables ¶
var ( ErrAdminRequired = errors.New("administrator access is required") ErrCannotDeleteSelf = errors.New("you cannot delete your own account") ErrLastAdmin = errors.New("the last administrator cannot be deleted") ErrManualSyncQueueFull = errors.New("manual synchronization queue is full; try again later") ErrInvalidUsername = errors.New("username must be 3-32 characters using letters, numbers, dots, underscores, or hyphens") ErrUsernameTaken = errors.New("that username is already in use") ErrInvalidNotificationHoldAction = errors.New("invalid notification hold action") )
var ( // ErrInvalidReleaseTruthProvider means the requested source is unsupported. ErrInvalidReleaseTruthProvider = errors.New("invalid release truth provider") // persisted observation for this release. ErrReleaseTruthProviderUnavailable = errors.New("release truth provider is unavailable") )
Functions ¶
func ProviderHealthStaleAfter ¶ added in v0.39.0
ProviderHealthStaleAfter returns the maximum useful age of a successful provider check for the health display. It intentionally uses a conservative multiple of each provider's normal cadence so a slow but functioning provider is not presented as unavailable.
func ProviderHealthStatus ¶ added in v0.39.0
ProviderHealthStatus is the single status policy used by both the web health view and administrator diagnostics. A failure newer than the last success always wins; an old success becomes stale rather than remaining indefinitely healthy.
func ProviderStatusOrder ¶ added in v0.22.0
func ProviderStatusOrder(statuses []ArtistProviderStatus)
ProviderStatusOrder keeps the Trust Center stable even when providers are first seen in a different order after a fallback.
Types ¶
type AdminArtist ¶
type AdminDeliveryHistory ¶
type AdminDestinationHealth ¶ added in v0.30.0
type Artist ¶
type Artist struct {
ID int64
MBID string
Name string
SortName string
Type string
Country string
Disambiguation string
SpotifyID string
SpotifyURL string
SpotifyImageURL string
Genres []string
ListenCount int64
ListenUsers int64
ListenCheckedAt *time.Time
LastCheckedAt *time.Time
SpotifyNextCheckAt *time.Time
BaselineSynced bool
}
type ArtistBreakdown ¶ added in v0.15.0
type ArtistCoverage ¶ added in v0.22.0
type ArtistCoverage struct {
Artist Artist
OverallStatus string
AssuranceStatus string
AssuranceReason string
LastSuccessfulProvider string
ProviderStatuses []ArtistProviderStatus
ReleaseCount int
ConfirmedReleases int
SingleSourceReleases int
FallbackReleases int
LastObservedAt *time.Time
NextCheckAt *time.Time
}
type ArtistProviderStatus ¶ added in v0.22.0
type ArtistProviderStatus struct {
ArtistID int64
Provider string
Status string
LastAttemptAt *time.Time
LastSuccessAt *time.Time
LastFailureAt *time.Time
NextCheckAt *time.Time
ReleaseCount int
LastError string
UpdatedAt time.Time
}
ArtistProviderStatus records the last known state of one provider for one followed artist. It is intentionally separate from provider_health, which describes the process-wide provider cooldown and not an individual artist.
type ArtistResolution ¶
type AssuranceSummary ¶ added in v0.32.0
type AssuranceSummary struct {
Total int
Healthy int
Delayed int
Degraded int
Pending int
AtRisk []ArtistCoverage
}
AssuranceSummary is the actionable, freshness-oriented view of a user's watchlist. AtRisk contains a small severity-ranked subset for dashboard rendering; the complete coverage page remains paginated separately.
type CalendarRelease ¶ added in v0.28.0
CalendarRelease is an owner-scoped release projection used by the calendar page, ICS export, and digest builder. Held is deliberately derived from the requesting user's notification hold state and never changes shared release metadata.
type CoverageSummary ¶ added in v0.22.0
type DeliveryHistory ¶
type Destination ¶
type DestinationHealth ¶ added in v0.30.0
type DestinationHealth struct {
DestinationID int64
Status string
ConsecutiveFailures int
PendingCount int
FailedCount int
LastSuccessAt *time.Time
LastFailureAt *time.Time
NextRetryAt *time.Time
LastError string
UpdatedAt time.Time
}
DestinationHealth is durable, owner-visible delivery state. It is kept separate from Destination so encrypted credentials and service metadata are never mixed into operational status projections.
type DiagnosticsProvider ¶ added in v0.32.0
DiagnosticsProvider is the redacted provider projection used by support reports. Error text and all credentials remain outside this type.
type DiagnosticsSnapshot ¶ added in v0.32.0
type DiagnosticsSnapshot struct {
CheckedAt time.Time
DatabaseHealthy bool
SchemaVersion int
FollowedArtists int
Releases int
QueuedSyncs int
RunningSyncs int
PendingDeliveries int
FailedDeliveries int
RecentLogEntries int
Providers []DiagnosticsProvider
}
DiagnosticsSnapshot contains safe operational counters for the admin support view. It intentionally excludes provider error text, credentials, notification bodies, and destination URLs.
type DigestDelivery ¶ added in v0.28.0
type DigestDelivery struct {
ID int64
RunID int64
Destination Destination
Title string
Body string
Attempts int
NextAttempt time.Time
}
DigestDelivery is a queued delivery for one generated release digest. It uses the same encrypted destination and retry semantics as normal events, but keeps one aggregate message per digest period instead of attaching the message to an individual release event.
type EvidenceIssue ¶ added in v0.25.0
type EvidenceIssue struct {
ID int64
ReleaseGroupID int64
ArtistID int64
ArtistName string
ReleaseTitle string
IssueType string
Severity string
Fingerprint string
Summary string
Evidence []ReleaseEvidence
Status string
ReviewState string
SnoozedUntil *time.Time
FirstSeenAt time.Time
LastSeenAt time.Time
ResolvedAt *time.Time
}
EvidenceIssue describes a provider disagreement or a release that has not yet been confirmed by the canonical catalog. The review state is private to the requesting user and does not alter release or notification semantics.
type FollowNotificationRule ¶ added in v0.31.0
type FollowNotificationRule struct {
UserID int64
ArtistID int64
DeliveryMode string
IncludePrimary bool
IncludeFeatured bool
Albums bool
EPs bool
Singles bool
Compilations bool
Announcements bool
ReleaseDay bool
PausedUntil *time.Time
UpdatedAt time.Time
}
FollowNotificationRule controls how one followed artist contributes to a member's notification stream. The inherit mode preserves the account-wide notification and digest preferences; other modes let a member make a noisy or especially important follow more specific without changing shared release data.
func (FollowNotificationRule) AllowsContent ¶ added in v0.31.0
func (r FollowNotificationRule) AllowsContent(primaryType, creditRole, eventType string, now time.Time) bool
AllowsContent determines whether an event for this follow should exist in the member's notification/inbox history. DeliveryMode is intentionally not considered here: digest and paused rules retain the event for visibility, while deciding whether a destination receives it is handled separately.
type ITunesArtworkArtist ¶ added in v0.12.1
ITunesArtworkArtist identifies one artist whose existing iTunes releases are due for an artwork-only refresh. Artwork backfills deliberately operate on existing rows and never create releases or notification events.
type ImportInput ¶
type ImportInput struct {
SourceValue string
DisplayName string
MBID string
MBURL string
SpotifyID string
SpotifyURL string
Reason string
}
ImportInput is a validated ArtistTrackarr export row. Validation belongs to the web package; the store deliberately accepts only the canonical fields needed to create a local artist and follow.
type ImportJob ¶
type ImportJob struct {
ID int64
UserID int64
CreatedAt time.Time
Rows []ImportRow
Added int
AlreadyFollowed int
Invalid int
}
ImportJob is the owner-scoped record for one CSV upload.
type ImportRow ¶
type ImportRow struct {
ID int64
JobID int64
SourceValue string
DisplayName string
Status string
ArtistID *int64
Reason string
}
ImportRow records the independent result for one CSV data row.
type ListenBrainzStats ¶ added in v0.15.0
type MaintenanceStats ¶
type MaintenanceStats struct {
Sessions int64
AuthTokens int64
LoginAttempts int64
ManualSyncs int64
ImportJobs int64
}
PruneExpiredState removes only expired or completed transient state. It deliberately leaves active sessions, current login blocks, queued work, and notification/delivery history untouched.
type ManualSyncRequest ¶
type NotificationHold ¶ added in v0.27.0
type NotificationHold struct {
ID int64
UserID int64
ReleaseGroupID int64
ArtistName string
ReleaseTitle string
EventType string
Title string
Body string
Reason string
IssueFingerprint string
PlannedAt time.Time
Status string
CreatedAt time.Time
ReleasedAt *time.Time
}
NotificationHold is an owner-scoped notification that was kept out of the delivery queue while provider evidence was conflicting. The original event content is retained so releasing a hold is deterministic and auditable.
type NotificationPreferences ¶
type NotificationPreferences struct {
UserID int64
Albums bool
EPs bool
Singles bool
Announcements bool
ReleaseDay bool
// DigestEnabled enables a compact upcoming-release digest delivered at
// the user's existing reminder time.
DigestEnabled bool
DigestFrequency string
// HoldConflictingNotifications keeps warning/critical provider conflicts
// out of deliveries until a household member explicitly reviews them.
// It defaults to false so existing accounts retain immediate notifications.
HoldConflictingNotifications bool
}
type ProviderHealth ¶
type Release ¶
type Release struct {
ID int64
MBID string
ArtistID int64
ArtistName string
Title string
PrimaryType string
SecondaryTypes []string
FirstReleaseDate string
DatePrecision int
MusicBrainzURL string
SpotifyID string
SpotifyURL string
SpotifyImageURL string
ITunesID string
ITunesURL string
ITunesArtworkURL string
// ArtistCreditRole records how the followed artist is credited by the
// provider. Spotify can return releases through appears_on when the
// artist is featured on another artist's release.
ArtistCreditRole string
// FollowedArtists lists the member's followed artists associated with this
// release. It is populated on detail/message projections and is not used as
// the canonical release artist identity.
FollowedArtists []string
// Credits contains provider-specific credit evidence for this release. It
// is populated on newly observed releases and on release-detail views; the
// release-level ArtistCreditRole remains the compatibility projection used
// by existing notification rules and queries.
Credits []ReleaseCredit
GuestCreditCount int
Source string
SourceCount int
Sources []string
Confidence string
TruthState string
TruthProvider string
TruthProviderID string
TruthReason string
TruthUpdatedAt *time.Time
TruthIssueCount int
LastObservedAt *time.Time
FirstObservedAt time.Time
}
type ReleaseBatch ¶
type ReleaseCredit ¶ added in v0.33.0
type ReleaseCredit struct {
ID int64
ReleaseGroupID int64
ArtistID int64
Provider string
ProviderID string
Role string
TrackTitle string
CreditName string
ProviderURL string
Confidence string
FirstSeenAt time.Time
LastSeenAt time.Time
}
ReleaseCredit records why a followed artist is associated with a release. A release can have several provider-backed credits (for example a primary Spotify credit and a guest MusicBrainz recording credit). Credit evidence is append-only apart from its last-seen timestamp so provider outages never erase a previously trustworthy relationship.
type ReleaseDetail ¶
type ReleaseDetail struct {
Release
Observations []ReleaseObservation
Credits []ReleaseCredit
Timeline []ReleaseTimelineEntry
}
type ReleaseEvidence ¶ added in v0.25.0
type ReleaseEvidence struct {
Provider string
ProviderID string
Title string
PrimaryType string
FirstReleaseDate string
DatePrecision int
ProviderURL string
ArtistCreditRole string
ObservedAt time.Time
}
ReleaseEvidence is the small normalized provider snapshot used to explain an evidence issue. Raw provider payloads and credentials are never stored.
type ReleaseInboxItem ¶ added in v0.24.0
type ReleaseInboxItem struct {
Release
EventType string
EventTitle string
EventCreatedAt time.Time
State string
SnoozedUntil *time.Time
}
ReleaseInboxItem is the latest alertable event for one followed release, together with the member's local review state. Inbox state never changes provider observations or notification delivery state.
type ReleaseObservation ¶
type ReleaseTimelineEntry ¶ added in v0.35.0
type ReleaseTimelineEntry struct {
Kind string
Provider string
Role string
Status string
Summary string
OccurredAt time.Time
}
ReleaseTimelineEntry is a redacted, owner-scoped explanation of the observations and decisions that shaped a release. It deliberately contains normalized summaries only; provider payloads, credentials, and notification bodies never enter the timeline projection.
type ReleaseTruthDecision ¶ added in v0.26.0
type ReleaseTruthDecision struct {
ReleaseGroupID int64
State string
SelectedProvider string
SelectedProviderID string
Reason string
DecidedByUserID *int64
CreatedAt time.Time
UpdatedAt time.Time
}
ReleaseTruthDecision is an explicit, reversible source choice for a release. It never overwrites provider observations or canonical metadata.
type ResolutionCandidate ¶
type ResolutionCandidate struct {
MBID string `json:"mbid"`
Name string `json:"name"`
SortName string `json:"sort_name"`
Type string `json:"type"`
Country string `json:"country"`
Disambiguation string `json:"disambiguation"`
Aliases []string `json:"aliases,omitempty"`
Genres []string `json:"genres,omitempty"`
Score int `json:"score"`
}
func (ResolutionCandidate) Artist ¶
func (c ResolutionCandidate) Artist() Artist
type SpotifyPollingState ¶
type Store ¶
Store keeps writes on a single connection while allowing read-only queries to use a small pool. SQLite WAL mode lets readers proceed while the writer is committing, which keeps dashboard requests from queueing behind provider synchronization work.
func (*Store) AddDestination ¶
func (*Store) AdminArtists ¶
func (s *Store) AdminArtists(ctx context.Context) ([]AdminArtist, error)
func (*Store) AdminDeliveryDetail ¶ added in v0.23.0
func (*Store) AdminDeliveryHistory ¶
func (*Store) AdminDeliveryHistoryCount ¶
func (*Store) AdminDeliveryHistorySummary ¶ added in v0.23.0
func (s *Store) AdminDeliveryHistorySummary(ctx context.Context, limit, offset int) ([]AdminDeliveryHistory, error)
AdminDeliveryHistorySummary deliberately omits notification bodies and provider error strings from the normal admin page. An administrator can request one specific record through AdminDeliveryDetail when investigation requires the full content, keeping bulk household data out of routine HTML.
func (*Store) AdminDestinationHealth ¶ added in v0.30.0
func (s *Store) AdminDestinationHealth(ctx context.Context) ([]AdminDestinationHealth, error)
AdminDestinationHealth is a compact household-wide view used by the admin dashboard. It never includes encrypted destination URLs or message bodies.
func (*Store) ApplicationLogs ¶
func (*Store) ApplyITunesArtworkBackfill ¶ added in v0.12.1
func (s *Store) ApplyITunesArtworkBackfill(ctx context.Context, artistID int64, releases []Release, observed time.Time) (checked, updated int, err error)
ApplyITunesArtworkBackfill updates only already persisted release rows. A successful response without artwork receives a long negative-cache period; it does not affect normal catalog scheduling or notifications.
func (*Store) ApplyReleaseBatches ¶
func (*Store) ApplyReleaseSync ¶
func (*Store) ArtistByID ¶
func (*Store) ArtistByMBID ¶
func (*Store) ArtistGenres ¶ added in v0.15.0
func (*Store) ArtistResolution ¶
func (*Store) ArtistResolutions ¶
func (*Store) ArtistsDue ¶
func (*Store) CalendarReleases ¶ added in v0.28.0
func (s *Store) CalendarReleases(ctx context.Context, userID int64, from, to string, limit int) ([]CalendarRelease, error)
CalendarReleases returns precise, dated releases for one followed artist watchlist within an inclusive ISO date range. Partial dates are intentionally excluded from ICS output because assigning them to a day would be misleading.
func (*Store) CancelArtistResolution ¶
func (*Store) ClaimManualSyncRequests ¶
func (*Store) ClearLoginFailures ¶
func (*Store) ClearReleaseTruthDecision ¶ added in v0.26.0
ClearReleaseTruthDecision removes a source choice for a followed release. Removing it restores the explainable automatic confidence state.
func (*Store) CompleteArtistResolution ¶
func (*Store) CompleteManualSyncRequest ¶
func (*Store) ConsumeAuthToken ¶
func (*Store) CoverageOverview ¶ added in v0.32.0
func (s *Store) CoverageOverview(ctx context.Context, userID int64, limit int) (CoverageSummary, AssuranceSummary, error)
CoverageOverview returns the summary used by the dashboard and Trust Center in one batched projection. This avoids repeating the followed-artist, provider-status, and release-stat queries when both views are rendered.
func (*Store) CoverageSummary ¶ added in v0.22.0
func (*Store) CreateArtistResolution ¶
func (*Store) CreateAuthToken ¶
func (*Store) CreateImportJob ¶
func (*Store) CreateManualSyncRequest ¶
func (*Store) CreateSession ¶
func (*Store) CreateUser ¶
func (*Store) CreateUserFromInvite ¶ added in v0.16.0
func (s *Store) CreateUserFromInvite(ctx context.Context, raw, hash, username, timezone string) error
CreateUserFromInvite consumes an invitation and creates its account in one transaction. Validation and uniqueness failures therefore leave the token available for correction and retry.
func (*Store) DashboardReleases ¶
func (*Store) DeleteDestination ¶
func (*Store) DeleteUser ¶
func (*Store) DeliveryHistory ¶
func (*Store) Destination ¶
func (*Store) DestinationHealthByUser ¶ added in v0.30.0
func (s *Store) DestinationHealthByUser(ctx context.Context, userID int64) (map[int64]DestinationHealth, error)
DestinationHealthByUser returns health for every destination owned by the user. Destinations created before the assurance migration are treated as healthy until their first delivery attempt.
func (*Store) Destinations ¶
func (*Store) Diagnostics ¶ added in v0.32.0
func (s *Store) Diagnostics(ctx context.Context) (DiagnosticsSnapshot, error)
Diagnostics returns bounded operational counters for the administrator support view. It deliberately omits error text and all destination/provider credentials so the resulting report is safe to copy into an issue.
func (*Store) DueArtistResolutions ¶
func (*Store) DueDeliveries ¶
func (*Store) DueDigestDeliveries ¶ added in v0.28.0
func (s *Store) DueDigestDeliveries(ctx context.Context, now time.Time, limit int) ([]DigestDelivery, error)
DueDigestDeliveries returns aggregate release-digest deliveries ready for the same notification worker used by normal release events.
func (*Store) DueITunesArtworkArtist ¶ added in v0.12.1
func (s *Store) DueITunesArtworkArtist(ctx context.Context, now time.Time) (ITunesArtworkArtist, bool, error)
DueITunesArtworkArtist returns at most one artist per call so the background runner can spread artwork requests over time and respect Apple's limiter.
func (*Store) DueListenBrainzArtists ¶ added in v0.15.0
func (*Store) EnqueueEvent ¶
func (*Store) EvidenceIssueCount ¶ added in v0.25.0
func (*Store) EvidenceIssueUnreadCount ¶ added in v0.25.0
func (*Store) EvidenceIssues ¶ added in v0.25.0
func (*Store) EvidenceIssuesForRelease ¶ added in v0.25.0
func (*Store) FinishDeliveryAttempt ¶ added in v0.30.0
func (s *Store) FinishDeliveryAttempt(ctx context.Context, attemptID, destinationID int64, success bool, message string, nextRetry *time.Time, finished time.Time) error
FinishDeliveryAttempt updates the attempt and destination circuit state in one writer transaction. Five consecutive failures pause the destination; a successful send clears the failure streak.
func (*Store) FollowNotificationRule ¶ added in v0.31.0
func (*Store) FollowNotificationRules ¶ added in v0.31.0
func (s *Store) FollowNotificationRules(ctx context.Context, userID int64, artistIDs []int64) (map[int64]FollowNotificationRule, error)
FollowNotificationRules returns rules for the requested follows. A nil or empty artist list loads every follow for the owner, which is useful for the digest builder; requested IDs that predate the migration receive the same safe inherit defaults as a newly-created follow.
func (*Store) FollowedArtistCount ¶
func (*Store) FollowedArtistCoveragePage ¶ added in v0.22.0
func (s *Store) FollowedArtistCoveragePage(ctx context.Context, userID int64, limit, offset int) ([]ArtistCoverage, error)
FollowedArtistCoveragePage returns a bounded, owner-scoped view suitable for the Trust Center. Provider status and release provenance are loaded in batches so large watchlists do not create one query per artist.
func (*Store) FollowedArtists ¶
func (*Store) FollowedArtistsFiltered ¶ added in v0.15.0
func (*Store) FollowedArtistsFilteredCount ¶ added in v0.21.0
func (s *Store) FollowedArtistsFilteredCount(ctx context.Context, userID int64, genre, country, artistType string) (int, error)
FollowedArtistsFilteredCount counts the distinct canonical artists matching the same filters used by FollowedArtistsFilteredPage.
func (*Store) FollowedArtistsFilteredPage ¶ added in v0.21.0
func (s *Store) FollowedArtistsFilteredPage(ctx context.Context, userID int64, genre, country, artistType string, limit, offset int) ([]Artist, error)
FollowedArtistsFilteredPage returns one alphabetically ordered page of the user's followed artists. Metadata enrichment is applied to only the page, keeping large watchlists from producing an oversized response or doing unnecessary work for artists outside the current page.
func (*Store) FollowedBreakdown ¶ added in v0.15.0
func (*Store) InsertApplicationLog ¶
func (*Store) IsFollowing ¶
func (*Store) LatestSpotifyReleaseDate ¶
func (*Store) LoginAllowed ¶
func (*Store) ManualSyncRequests ¶
func (*Store) MarkArtistChecked ¶
func (*Store) MarkArtistResolutionReview ¶
func (*Store) MarkDeliveryFailed ¶
func (*Store) MarkDeliverySent ¶
func (*Store) MarkDigestDeliveryFailed ¶ added in v0.28.0
func (*Store) MarkDigestDeliverySent ¶ added in v0.28.0
func (*Store) MarkSpotifyChecked ¶
func (*Store) MarkSpotifyCheckedAdaptive ¶
func (*Store) NotificationHolds ¶ added in v0.27.0
func (s *Store) NotificationHolds(ctx context.Context, userID int64, limit int) ([]NotificationHold, error)
NotificationHolds returns pending holds for one household member.
func (*Store) NotificationHoldsForRelease ¶ added in v0.27.0
func (s *Store) NotificationHoldsForRelease(ctx context.Context, userID, releaseID int64) ([]NotificationHold, error)
NotificationHoldsForRelease returns pending holds for a followed release.
func (*Store) NotificationPreferences ¶
func (*Store) PauseFollowNotificationRule ¶ added in v0.31.0
func (*Store) ProviderHealth ¶
func (s *Store) ProviderHealth(ctx context.Context) ([]ProviderHealth, error)
func (*Store) ProviderHealthByName ¶
ProviderHealthByName returns the persisted state for one provider. The scheduler uses the next check time to carry a provider-wide cooldown across process restarts, so a quota response cannot cause a fresh burst of calls after the container is recreated.
func (*Store) PruneApplicationLogs ¶
func (*Store) PruneExpiredState ¶
func (*Store) QueueDueReleaseDays ¶
func (*Store) QueueDueReleaseDigests ¶ added in v0.28.0
QueueDueReleaseDigests creates at most one aggregate digest run per user and local period. It deliberately reuses the normal destination encryption and retry path, while keeping aggregate content separate from per-release notification event uniqueness.
func (*Store) RecentReleases ¶
func (*Store) RecordArtistProviderStatus ¶ added in v0.22.0
func (s *Store) RecordArtistProviderStatus(ctx context.Context, status ArtistProviderStatus) error
RecordArtistProviderStatus persists an individual artist/provider outcome. ReleaseCount may be set to -1 when an outcome did not return a release batch; in that case the previously observed count is retained.
func (*Store) RecordLoginFailure ¶
func (*Store) ReleaseDetail ¶
func (*Store) ReleaseInbox ¶ added in v0.24.0
func (s *Store) ReleaseInbox(ctx context.Context, userID int64, state, source, primaryType string, limit, offset int, now time.Time) ([]ReleaseInboxItem, error)
ReleaseInbox returns the latest alertable event for each followed release. Historical releases that were silently baselined never have a notification event and therefore do not appear here.
func (*Store) ReleaseInboxCount ¶ added in v0.24.0
func (*Store) ReleaseInboxUnreadCount ¶ added in v0.24.0
func (*Store) ReleaseTimeline ¶ added in v0.35.0
func (s *Store) ReleaseTimeline(ctx context.Context, userID, releaseID int64) ([]ReleaseTimelineEntry, error)
ReleaseTimeline returns a redacted explanation of the provider observations, credits, reviews, notification decisions, and delivery state for one release visible to the requesting household member. It is derived from existing projections so it cannot alter release or notification semantics.
func (*Store) RenameDestination ¶
func (*Store) ResetPasswordWithToken ¶ added in v0.23.0
ResetPasswordWithToken updates the password, revokes existing sessions, and consumes a reset token in one transaction. A transient database failure no longer burns a still-valid recovery link.
func (*Store) ResolveNotificationHold ¶ added in v0.27.0
func (s *Store) ResolveNotificationHold(ctx context.Context, userID, holdID int64, action string) error
ResolveNotificationHold either sends the held event through the normal delivery queue or discards it. Both actions are owner-scoped and atomic.
func (*Store) RetryArtistResolution ¶
func (*Store) RetryFailedDeliveries ¶ added in v0.30.0
func (s *Store) RetryFailedDeliveries(ctx context.Context, userID, destinationID int64, now time.Time) (int, error)
RetryFailedDeliveries requeues all permanently failed deliveries for an owned destination. It is intentionally owner-scoped and resets the circuit only after the queue has been made runnable.
func (*Store) SaveArtistGenres ¶ added in v0.15.0
func (*Store) SaveImportRow ¶
func (s *Store) SaveImportRow(ctx context.Context, userID, jobID int64, input ImportInput) (ImportRow, error)
SaveImportRow persists one row and, for valid input, creates or reuses the canonical artist and owner-scoped follow in the same transaction. This makes partial uploads durable without coupling them to provider availability.
func (*Store) SaveListenBrainzStats ¶ added in v0.15.0
func (*Store) ScheduleArtistCheck ¶
func (*Store) ScheduleITunesArtworkRetry ¶ added in v0.12.1
func (s *Store) ScheduleITunesArtworkRetry(ctx context.Context, artistID int64, next time.Time) error
ScheduleITunesArtworkRetry applies a bounded durable retry time to all existing artwork gaps for an artist after a transient provider failure.
func (*Store) ScheduleListenBrainzRefresh ¶ added in v0.35.0
func (s *Store) ScheduleListenBrainzRefresh(ctx context.Context, artistIDs []int64, next time.Time) error
ScheduleListenBrainzRefresh advances refresh timestamps for artists that were absent from an otherwise successful provider response. Existing aggregate totals are intentionally untouched.
func (*Store) ScheduleListenBrainzRetry ¶ added in v0.15.0
func (*Store) ScheduleSpotifyCheck ¶
func (*Store) SetEvidenceIssueState ¶ added in v0.25.0
func (*Store) SetFollowNotificationDeliveryMode ¶ added in v0.31.0
func (s *Store) SetFollowNotificationDeliveryMode(ctx context.Context, userID int64, artistIDs []int64, mode string) (int, error)
SetFollowNotificationDeliveryMode updates only the mode for a selected group, preserving each artist's release-type and credit filters.
func (*Store) SetReleaseInboxState ¶ added in v0.24.0
func (s *Store) SetReleaseInboxState(ctx context.Context, userID, releaseID int64, state string, snoozedUntil *time.Time) error
SetReleaseInboxState changes only the requesting member's review state. A release must still have an alertable event for that member, preventing cross-user access and accidental state rows for arbitrary release IDs.
func (*Store) SetReleaseTruthDecision ¶ added in v0.26.0
func (s *Store) SetReleaseTruthDecision(ctx context.Context, userID, releaseID int64, provider, reason string) error
SetReleaseTruthDecision records a household-scoped, reversible source choice after verifying that the caller follows the release's artist. The decision is deliberately separate from release_groups and provider observations so it cannot rewrite canonical data or affect notifications.
func (*Store) SpotifyBatchChanged ¶
SpotifyBatchChanged reports whether a successful provider response contains a release that is new or has changed since it was last observed. It is intentionally read before the release transaction so the scheduler can persist its adaptive state together with the completed observation.
func (*Store) SpotifyPollingState ¶
func (*Store) StartDeliveryAttempt ¶ added in v0.30.0
func (s *Store) StartDeliveryAttempt(ctx context.Context, deliveryID, digestDeliveryID int64, destination Destination, attemptNumber int, started time.Time) (int64, error)
StartDeliveryAttempt records an attempt before decryption and network I/O. Keeping the destination name/service snapshot here makes the audit useful even if the destination is renamed or removed later.
func (*Store) TopListenBrainzArtists ¶ added in v0.15.0
func (*Store) UpdateFollowNotificationRule ¶ added in v0.31.0
func (*Store) UpdateFollowNotificationRules ¶ added in v0.31.0
func (s *Store) UpdateFollowNotificationRules(ctx context.Context, userID int64, artistIDs []int64, rule FollowNotificationRule) (int, error)
UpdateFollowNotificationRules applies one complete policy to a set of owner-scoped follows. It validates all IDs before changing any row, so a mixed or cross-user submission cannot partially update a batch.
func (*Store) UpdateNotificationPreferences ¶
func (s *Store) UpdateNotificationPreferences(ctx context.Context, p NotificationPreferences) error
func (*Store) UpdatePassword ¶
func (*Store) UpdateProfile ¶
func (*Store) UpsertArtist ¶
func (*Store) UpsertProviderHealth ¶
func (*Store) UserByEmail ¶
func (*Store) ValidateDestinationCiphertexts ¶ added in v0.38.0
func (s *Store) ValidateDestinationCiphertexts(ctx context.Context, decrypt func([]byte) (string, error)) error
ValidateDestinationCiphertexts verifies that every persisted destination can be opened with the configured application key. It deliberately returns only the destination ID and a generic error; ciphertext and provider credentials never enter logs or user-facing responses. Startup uses this check during restore rehearsals so a wrong key cannot produce a seemingly healthy but unusable application.
func (*Store) WatchlistAssurance ¶ added in v0.32.0
func (s *Store) WatchlistAssurance(ctx context.Context, userID int64, limit int) (AssuranceSummary, error)
WatchlistAssurance returns the complete owner-scoped assurance counts and a small severity-ranked list for dashboard use. The underlying projections are batched, matching the Trust Center's query behavior.