feat: add multi-source breed encyclopedia and two-hour refresh sessions
ci-cd / verify (push) Successful in 1m59s
ci-cd / deploy (push) Skipped

This commit is contained in:
2026-10-05 13:38:24 +08:00
parent 607d709100
commit 9d7cf720a5
73 changed files with 25771 additions and 264 deletions
+54 -2
View File
@@ -47,12 +47,64 @@ type Admin struct {
PasswordHash string `gorm:"size:255;not null" json:"-"`
}
// RefreshSession stores only a hash of the rotating refresh credential.
type RefreshSession struct {
Base
ActorID string `gorm:"type:uuid;index;not null" json:"-"`
Role string `gorm:"size:16;index;not null" json:"-"`
TokenHash string `gorm:"size:64;uniqueIndex;not null" json:"-"`
ExpiresAt time.Time `gorm:"index;not null" json:"-"`
Revoked bool `gorm:"not null;default:false" json:"-"`
}
type Breed struct {
Base
LifeSpan string `gorm:"size:128" json:"life_span"`
Exercise string `gorm:"size:255" json:"exercise"`
Grooming string `gorm:"size:255" json:"grooming"`
EditorialLocked bool `gorm:"not null;default:false" json:"editorial_locked"`
FieldSources map[string]string `gorm:"serializer:json;type:jsonb" json:"field_sources"`
References []BreedReference `gorm:"foreignKey:BreedID" json:"references,omitempty"`
Origin string `gorm:"size:128" json:"origin"`
BreedGroup string `gorm:"size:255" json:"breed_group"`
FCINumber string `gorm:"size:16" json:"fci_number"`
Height string `gorm:"size:128" json:"height"`
Weight string `gorm:"size:128" json:"weight"`
Summary string `gorm:"type:text" json:"summary"`
Temperament string `gorm:"size:255" json:"temperament"`
Traits string `gorm:"type:text" json:"traits"`
CareNotes string `gorm:"type:text" json:"care_notes"`
EncyclopediaUpdatedAt string `gorm:"size:10" json:"encyclopedia_updated_at"`
Name string `gorm:"size:128;uniqueIndex;not null" json:"name"`
EnglishName string `gorm:"size:128" json:"english_name"`
Aliases string `gorm:"size:512" json:"aliases"`
Pinyin string `gorm:"size:1024;index;not null" json:"pinyin"`
PinyinInitials string `gorm:"size:128" json:"pinyin_initials"`
Initial string `gorm:"size:1;index;not null" json:"initial"`
Enabled bool `gorm:"not null;default:true" json:"enabled"`
Source string `gorm:"size:128" json:"source"`
SourceKey *string `gorm:"size:128;uniqueIndex" json:"source_key"`
SourceURL string `gorm:"size:512" json:"source_url"`
}
// Facts contain short structured facts, never copied articles or remote images.
type BreedReference struct {
Base
BreedID string `gorm:"type:uuid;uniqueIndex:idx_breed_provider;not null" json:"breed_id"`
Provider string `gorm:"size:32;uniqueIndex:idx_breed_provider;not null" json:"provider"`
ExternalID string `gorm:"size:128;not null" json:"external_id"`
URL string `gorm:"size:512;not null" json:"url"`
RetrievedAt string `gorm:"size:10;not null" json:"retrieved_at"`
Facts map[string]string `gorm:"serializer:json;type:jsonb;not null" json:"facts"`
}
type Pet struct {
Base
UserID string `gorm:"type:uuid;index;not null" json:"user_id"`
Name string `gorm:"size:64;not null" json:"name"`
Species string `gorm:"size:16;not null;default:dog" json:"species"`
Breed string `gorm:"size:64" json:"breed"`
Breed string `gorm:"size:128" json:"breed"`
BreedID *string `gorm:"type:uuid;index" json:"breed_id"`
Gender string `gorm:"size:16" json:"gender"`
BirthDate *time.Time `gorm:"type:date" json:"birth_date"`
WeightKg float64 `gorm:"type:numeric(6,2)" json:"weight_kg"`
@@ -140,7 +192,7 @@ type MeetupPet struct {
func All() []any {
return []any{
&File{}, &User{}, &Admin{}, &Pet{}, &CareTask{}, &TaskCompletion{},
&File{}, &User{}, &Admin{}, &RefreshSession{}, &Breed{}, &BreedReference{}, &Pet{}, &CareTask{}, &TaskCompletion{},
&Walk{}, &WalkPet{}, &WalkPoint{}, &Meetup{}, &MeetupParticipant{}, &MeetupPet{},
}
}