Help us shape the future of Go! Take the 2026 Go Developer Survey

store

package
v0.39.0 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Index

Constants

View Source
const (
	FollowDeliveryInherit   = "inherit"
	FollowDeliveryImmediate = "immediate"
	FollowDeliveryDigest    = "digest"
	FollowDeliveryOff       = "off"
)

Variables

View Source
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")
)
View Source
var (
	// ErrInvalidReleaseTruthProvider means the requested source is unsupported.
	ErrInvalidReleaseTruthProvider = errors.New("invalid release truth provider")
	// ErrReleaseTruthProviderUnavailable means the provider is valid but has no
	// persisted observation for this release.
	ErrReleaseTruthProviderUnavailable = errors.New("release truth provider is unavailable")
)

Functions

func ProviderHealthStaleAfter added in v0.39.0

func ProviderHealthStaleAfter(provider string) time.Duration

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

func ProviderHealthStatus(provider ProviderHealth, now time.Time, staleAfter time.Duration) string

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 AdminArtist struct {
	ID   int64
	Name string
	MBID string
}

type AdminDeliveryHistory

type AdminDeliveryHistory struct {
	DeliveryID  int64
	UserEmail   string
	Title       string
	Body        string
	EventType   string
	Destination string
	Service     string
	Status      string
	Attempts    int
	LastError   string
	CreatedAt   time.Time
	NextAttempt *time.Time
	SentAt      *time.Time
}

type AdminDestinationHealth added in v0.30.0

type AdminDestinationHealth struct {
	DestinationID       int64
	UserEmail           string
	DestinationName     string
	Service             string
	Status              string
	ConsecutiveFailures int
	PendingCount        int
	FailedCount         int
	LastSuccessAt       *time.Time
	LastFailureAt       *time.Time
	NextRetryAt         *time.Time
	LastError           string
	UpdatedAt           time.Time
}

type AdminUser

type AdminUser struct {
	ID               int64
	Email            string
	Username         string
	Role             string
	Timezone         string
	ReminderTime     string
	FollowCount      int
	DestinationCount int
	CreatedAt        time.Time
}

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 ArtistBreakdown struct {
	Label string
	Count int
}

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 ArtistResolution struct {
	ID          int64
	UserID      int64
	Provider    string
	ProviderID  string
	DisplayName string
	ProviderURL string
	ImageURL    string
	Status      string
	Candidates  []ResolutionCandidate
	Attempts    int
	NextAttempt *time.Time
	LastError   string
	CreatedAt   time.Time
	UpdatedAt   time.Time
}

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

type CalendarRelease struct {
	Release
	CalendarDate string
	Held         bool
}

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 CoverageSummary struct {
	Artists                 int
	FreshArtists            int
	AttentionArtists        int
	PendingArtists          int
	ConfirmedReleases       int
	SingleSourceReleases    int
	FallbackReleases        int
	HealthyArtists          int
	DelayedArtists          int
	DegradedArtists         int
	PendingAssuranceArtists int
}

type Delivery

type Delivery struct {
	ID           int64
	EventID      int64
	Destination  Destination
	Title        string
	Body         string
	Attempts     int
	NextAttempt  time.Time
	EventType    string
	ReleaseTitle string
}

type DeliveryHistory

type DeliveryHistory struct {
	Title       string
	EventType   string
	Destination string
	Status      string
	Attempts    int
	LastError   string
	CreatedAt   time.Time
	SentAt      *time.Time
}

type Destination

type Destination struct {
	ID           int64
	UserID       int64
	Name         string
	Service      string
	EncryptedURL []byte
	Enabled      bool
}

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

type DiagnosticsProvider struct {
	Provider    string
	Status      string
	NextCheckAt *time.Time
}

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

type ITunesArtworkArtist struct {
	ID       int64
	Name     string
	Attempts int
}

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 ListenBrainzStats struct {
	ArtistID         int64
	MBID             string
	TotalListenCount int64
	TotalUserCount   int64
	CheckedAt        *time.Time
	NextCheckAt      *time.Time
	LastError        string
}

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 ManualSyncRequest struct {
	ID          int64
	RequestedBy int64
	Scope       string
	ArtistID    *int64
	Status      string
	CreatedAt   time.Time
	StartedAt   *time.Time
	FinishedAt  *time.Time
	LastError   string
}

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 ProviderHealth struct {
	Provider      string
	LastSuccessAt *time.Time
	LastFailureAt *time.Time
	LastError     string
	NextCheckAt   *time.Time
	RateLimited   bool
	QuotaExceeded bool
	UpdatedAt     time.Time
}

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 ReleaseBatch struct {
	Provider string
	Releases []Release
}

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 ReleaseObservation struct {
	Provider   string
	ProviderID string
	ObservedAt time.Time
}

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 Session

type Session struct {
	User      User
	CSRFToken string
	ExpiresAt time.Time
}

type SpotifyPollingState

type SpotifyPollingState struct {
	UnchangedChecks int
	LastChangeAt    *time.Time
}

type Store

type Store struct {
	DB     *sql.DB
	Reader *sql.DB
	// contains filtered or unexported fields
}

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 Open

func Open(path string) (*Store, error)

func (*Store) AddDestination

func (s *Store) AddDestination(ctx context.Context, userID int64, name, service string, encrypted []byte) error

func (*Store) AdminArtists

func (s *Store) AdminArtists(ctx context.Context) ([]AdminArtist, error)

func (*Store) AdminDeliveryDetail added in v0.23.0

func (s *Store) AdminDeliveryDetail(ctx context.Context, deliveryID int64) (AdminDeliveryHistory, error)

func (*Store) AdminDeliveryHistory

func (s *Store) AdminDeliveryHistory(ctx context.Context, limit, offset int) ([]AdminDeliveryHistory, error)

func (*Store) AdminDeliveryHistoryCount

func (s *Store) AdminDeliveryHistoryCount(ctx context.Context) (int, error)

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) AdminUsers

func (s *Store) AdminUsers(ctx context.Context) ([]AdminUser, error)

func (*Store) ApplicationLogs

func (s *Store) ApplicationLogs(ctx context.Context, limit int) ([]logging.Entry, error)

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 (s *Store) ApplyReleaseBatches(ctx context.Context, artist Artist, batches []ReleaseBatch, observed time.Time) error

func (*Store) ApplyReleaseSync

func (s *Store) ApplyReleaseSync(ctx context.Context, artist Artist, releases []Release, observed time.Time) error

func (*Store) ArtistByID

func (s *Store) ArtistByID(ctx context.Context, id int64) (Artist, error)

func (*Store) ArtistByMBID

func (s *Store) ArtistByMBID(ctx context.Context, mbid string) (Artist, error)

func (*Store) ArtistGenres added in v0.15.0

func (s *Store) ArtistGenres(ctx context.Context, artistID int64) ([]string, error)

func (*Store) ArtistResolution

func (s *Store) ArtistResolution(ctx context.Context, userID, resolutionID int64) (ArtistResolution, error)

func (*Store) ArtistResolutions

func (s *Store) ArtistResolutions(ctx context.Context, userID int64) ([]ArtistResolution, error)

func (*Store) ArtistsDue

func (s *Store) ArtistsDue(ctx context.Context, now time.Time, limit int) ([]Artist, error)

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 (s *Store) CancelArtistResolution(ctx context.Context, userID, resolutionID int64) error

func (*Store) ClaimManualSyncRequests

func (s *Store) ClaimManualSyncRequests(ctx context.Context, limit int) ([]ManualSyncRequest, error)

func (*Store) ClearLoginFailures

func (s *Store) ClearLoginFailures(ctx context.Context, key string)

func (*Store) ClearReleaseTruthDecision added in v0.26.0

func (s *Store) ClearReleaseTruthDecision(ctx context.Context, userID, releaseID int64) error

ClearReleaseTruthDecision removes a source choice for a followed release. Removing it restores the explainable automatic confidence state.

func (*Store) Close

func (s *Store) Close() error

func (*Store) CompleteArtistResolution

func (s *Store) CompleteArtistResolution(ctx context.Context, resolution ArtistResolution, artist Artist) (Artist, bool, error)

func (*Store) CompleteManualSyncRequest

func (s *Store) CompleteManualSyncRequest(ctx context.Context, id int64, syncErr error) error

func (*Store) ConsumeAuthToken

func (s *Store) ConsumeAuthToken(ctx context.Context, raw, kind string) (email string, userID *int64, err error)

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 (s *Store) CoverageSummary(ctx context.Context, userID int64) (CoverageSummary, error)

func (*Store) CreateArtistResolution

func (s *Store) CreateArtistResolution(ctx context.Context, userID int64, provider, providerID, name, providerURL, imageURL string) (ArtistResolution, bool, error)

func (*Store) CreateAuthToken

func (s *Store) CreateAuthToken(ctx context.Context, kind, email string, userID *int64, creator int64, ttl time.Duration) (string, error)

func (*Store) CreateImportJob

func (s *Store) CreateImportJob(ctx context.Context, userID int64) (ImportJob, error)

func (*Store) CreateManualSyncRequest

func (s *Store) CreateManualSyncRequest(ctx context.Context, userID int64, scope string, artistID *int64) (ManualSyncRequest, error)

func (*Store) CreateSession

func (s *Store) CreateSession(ctx context.Context, userID int64, ttl time.Duration) (raw, csrf string, err error)

func (*Store) CreateUser

func (s *Store) CreateUser(ctx context.Context, email, hash, role, timezone, username string) (int64, error)

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 (s *Store) DashboardReleases(
	ctx context.Context, userID int64, today string, limit int,
) (upcoming []Release, recent []Release, err error)

func (*Store) DeleteDestination

func (s *Store) DeleteDestination(ctx context.Context, userID, id int64) error

func (*Store) DeleteSession

func (s *Store) DeleteSession(ctx context.Context, raw string) error

func (*Store) DeleteUser

func (s *Store) DeleteUser(ctx context.Context, actingAdminID, userID int64) error

func (*Store) DeliveryHistory

func (s *Store) DeliveryHistory(ctx context.Context, userID int64, limit int) ([]DeliveryHistory, error)

func (*Store) Destination

func (s *Store) Destination(ctx context.Context, userID, id int64) (Destination, error)

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 (s *Store) Destinations(ctx context.Context, userID int64) ([]Destination, error)

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 (s *Store) DueArtistResolutions(ctx context.Context, now time.Time, limit int) ([]ArtistResolution, error)

func (*Store) DueDeliveries

func (s *Store) DueDeliveries(ctx context.Context, now time.Time, limit int) ([]Delivery, error)

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 (s *Store) DueListenBrainzArtists(ctx context.Context, now time.Time, limit int) ([]Artist, error)

func (*Store) EnqueueEvent

func (s *Store) EnqueueEvent(ctx context.Context, userID, releaseID int64, eventType, title, body string, now time.Time) error

func (*Store) EvidenceIssueCount added in v0.25.0

func (s *Store) EvidenceIssueCount(ctx context.Context, userID int64, status, state, issueType, severity string, now time.Time) (int, error)

func (*Store) EvidenceIssueUnreadCount added in v0.25.0

func (s *Store) EvidenceIssueUnreadCount(ctx context.Context, userID int64, now time.Time) (int, error)

func (*Store) EvidenceIssues added in v0.25.0

func (s *Store) EvidenceIssues(ctx context.Context, userID int64, status, state, issueType, severity string, limit, offset int, now time.Time) ([]EvidenceIssue, error)

func (*Store) EvidenceIssuesForRelease added in v0.25.0

func (s *Store) EvidenceIssuesForRelease(ctx context.Context, userID, releaseID int64, now time.Time) ([]EvidenceIssue, error)

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) Follow

func (s *Store) Follow(ctx context.Context, userID, artistID int64) (bool, error)

func (*Store) FollowNotificationRule added in v0.31.0

func (s *Store) FollowNotificationRule(ctx context.Context, userID, artistID int64) (FollowNotificationRule, error)

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 (s *Store) FollowedArtistCount(ctx context.Context, userID int64) (int, error)

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 (s *Store) FollowedArtists(ctx context.Context, userID int64) ([]Artist, error)

func (*Store) FollowedArtistsFiltered added in v0.15.0

func (s *Store) FollowedArtistsFiltered(ctx context.Context, userID int64, genre, country, artistType string) ([]Artist, error)

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 (s *Store) FollowedBreakdown(ctx context.Context, userID int64, dimension string) ([]ArtistBreakdown, error)

func (*Store) Healthy

func (s *Store) Healthy(ctx context.Context) error

func (*Store) ImportJob

func (s *Store) ImportJob(ctx context.Context, userID, jobID int64) (ImportJob, error)

func (*Store) InsertApplicationLog

func (s *Store) InsertApplicationLog(ctx context.Context, entry logging.Entry) error

func (*Store) IsFollowing

func (s *Store) IsFollowing(ctx context.Context, userID, artistID int64) (bool, error)

func (*Store) LatestSpotifyReleaseDate

func (s *Store) LatestSpotifyReleaseDate(ctx context.Context, artistID int64) (string, error)

func (*Store) LoginAllowed

func (s *Store) LoginAllowed(ctx context.Context, key string) (bool, error)

func (*Store) ManualSyncRequests

func (s *Store) ManualSyncRequests(ctx context.Context, limit int) ([]ManualSyncRequest, error)

func (*Store) MarkAllArtistsDue

func (s *Store) MarkAllArtistsDue(ctx context.Context) error

func (*Store) MarkArtistChecked

func (s *Store) MarkArtistChecked(ctx context.Context, artistID int64, now time.Time, interval time.Duration) error

func (*Store) MarkArtistResolutionReview

func (s *Store) MarkArtistResolutionReview(ctx context.Context, userID, resolutionID int64, candidates []ResolutionCandidate) error

func (*Store) MarkDeliveryFailed

func (s *Store) MarkDeliveryFailed(ctx context.Context, id int64, attempts int, message string, now time.Time) error

func (*Store) MarkDeliverySent

func (s *Store) MarkDeliverySent(ctx context.Context, id int64, now time.Time) error

func (*Store) MarkDigestDeliveryFailed added in v0.28.0

func (s *Store) MarkDigestDeliveryFailed(ctx context.Context, id int64, attempts int, message string, now time.Time) error

func (*Store) MarkDigestDeliverySent added in v0.28.0

func (s *Store) MarkDigestDeliverySent(ctx context.Context, id int64, now time.Time) error

func (*Store) MarkSpotifyChecked

func (s *Store) MarkSpotifyChecked(ctx context.Context, artistID int64, now time.Time, interval time.Duration) error

func (*Store) MarkSpotifyCheckedAdaptive

func (s *Store) MarkSpotifyCheckedAdaptive(ctx context.Context, artistID int64, now time.Time, interval time.Duration, changed, upcoming bool) error

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 (s *Store) NotificationPreferences(ctx context.Context, userID int64) (NotificationPreferences, error)

func (*Store) PauseFollowNotificationRule added in v0.31.0

func (s *Store) PauseFollowNotificationRule(ctx context.Context, userID, artistID int64, until *time.Time) error

func (*Store) ProviderHealth

func (s *Store) ProviderHealth(ctx context.Context) ([]ProviderHealth, error)

func (*Store) ProviderHealthByName

func (s *Store) ProviderHealthByName(ctx context.Context, provider string) (ProviderHealth, error)

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 (s *Store) PruneApplicationLogs(ctx context.Context, before time.Time) error

func (*Store) PruneExpiredState

func (s *Store) PruneExpiredState(ctx context.Context, now time.Time) (MaintenanceStats, error)

func (*Store) QueueDueReleaseDays

func (s *Store) QueueDueReleaseDays(ctx context.Context, now time.Time) error

func (*Store) QueueDueReleaseDigests added in v0.28.0

func (s *Store) QueueDueReleaseDigests(ctx context.Context, now time.Time) (int, error)

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 (s *Store) RecentReleases(ctx context.Context, userID int64, limit int) ([]Release, error)

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 (s *Store) RecordLoginFailure(ctx context.Context, key string) error

func (*Store) ReleaseDetail

func (s *Store) ReleaseDetail(ctx context.Context, userID, releaseID int64) (ReleaseDetail, error)

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 (s *Store) ReleaseInboxCount(ctx context.Context, userID int64, state, source, primaryType string, now time.Time) (int, error)

func (*Store) ReleaseInboxUnreadCount added in v0.24.0

func (s *Store) ReleaseInboxUnreadCount(ctx context.Context, userID int64, now time.Time) (int, error)

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 (s *Store) RenameDestination(ctx context.Context, userID, destinationID int64, name string) error

func (*Store) ResetPasswordWithToken added in v0.23.0

func (s *Store) ResetPasswordWithToken(ctx context.Context, raw, hash string) error

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 (s *Store) RetryArtistResolution(ctx context.Context, userID, resolutionID int64, attempts int, next time.Time, message string) error

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 (s *Store) SaveArtistGenres(ctx context.Context, artistID int64, genres []string) error

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 (s *Store) SaveListenBrainzStats(ctx context.Context, stats map[int64]ListenBrainzStats, now, next time.Time) error

func (*Store) ScheduleArtistCheck

func (s *Store) ScheduleArtistCheck(ctx context.Context, artistID int64, next time.Time) error

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 (s *Store) ScheduleListenBrainzRetry(ctx context.Context, artistIDs []int64, next time.Time, message string) error

func (*Store) ScheduleSpotifyCheck

func (s *Store) ScheduleSpotifyCheck(ctx context.Context, artistID int64, next time.Time) error

func (*Store) Session

func (s *Store) Session(ctx context.Context, raw string) (Session, error)

func (*Store) SetEvidenceIssueState added in v0.25.0

func (s *Store) SetEvidenceIssueState(ctx context.Context, userID, issueID int64, state string, snoozedUntil *time.Time) error

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

func (s *Store) SpotifyBatchChanged(ctx context.Context, releases []Release) (bool, error)

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 (s *Store) SpotifyPollingState(ctx context.Context, artistID int64) (SpotifyPollingState, error)

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 (s *Store) TopListenBrainzArtists(ctx context.Context, userID int64, limit int) ([]Artist, error)

func (*Store) Unfollow

func (s *Store) Unfollow(ctx context.Context, userID, artistID int64) error

func (*Store) UpdateFollowNotificationRule added in v0.31.0

func (s *Store) UpdateFollowNotificationRule(ctx context.Context, userID, artistID int64, rule FollowNotificationRule) error

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 (s *Store) UpdatePassword(ctx context.Context, userID int64, hash string) error

func (*Store) UpdateProfile

func (s *Store) UpdateProfile(ctx context.Context, userID int64, timezone, reminder, username string) error

func (*Store) UpsertArtist

func (s *Store) UpsertArtist(ctx context.Context, a Artist) (Artist, error)

func (*Store) UpsertProviderHealth

func (s *Store) UpsertProviderHealth(ctx context.Context, provider string, success bool, next *time.Time, rateLimited, quota bool, lastError string) error

func (*Store) UserByEmail

func (s *Store) UserByEmail(ctx context.Context, email string) (User, error)

func (*Store) UserByID

func (s *Store) UserByID(ctx context.Context, id int64) (User, error)

func (*Store) UserCount

func (s *Store) UserCount(ctx context.Context) (int, error)

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.

type User

type User struct {
	ID           int64
	Email        string
	Username     string
	PasswordHash string
	Role         string
	Timezone     string
	ReminderTime string
	CreatedAt    time.Time
}

Jump to

Keyboard shortcuts

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