package domain import ( "context" "errors" "time" ) const ( KindJob = "job" KindSystem = "system" RefJob = "job" RefNone = "none" ) var ( ErrNotFound = errors.New("notification not found") ErrForbidden = errors.New("notification access denied") ) type Notification struct { ID string `bson:"_id" json:"id"` OwnerUID int64 `bson:"owner_uid" json:"owner_uid"` Title string `bson:"title" json:"title"` Body string `bson:"body" json:"body"` Kind string `bson:"kind" json:"kind"` RefType string `bson:"ref_type" json:"ref_type"` RefID string `bson:"ref_id,omitempty" json:"ref_id,omitempty"` ReadAt int64 `bson:"read_at,omitempty" json:"read_at,omitempty"` CreatedAt int64 `bson:"created_at" json:"created_at"` } func NowNano() int64 { return time.Now().UTC().UnixNano() } type Repository interface { Insert(ctx context.Context, n *Notification) error ListByOwner(ctx context.Context, ownerUID int64) ([]*Notification, error) UnreadCount(ctx context.Context, ownerUID int64) (int64, error) MarkRead(ctx context.Context, ownerUID int64, id string) error MarkAllRead(ctx context.Context, ownerUID int64) error FindByID(ctx context.Context, id string) (*Notification, error) // FindLatestByJobRef — 同一 job 的最新通知(用於進度 upsert) FindLatestByJobRef(ctx context.Context, ownerUID int64, jobID string) (*Notification, error) // Replace full document Replace(ctx context.Context, n *Notification) error }