feat: add NFT usernames and bot verification (#22)
Implements collectible usernames, official verification workflows, and third-party bot verification after maintainer protocol and migration review. The composite activity/moderation rating remains an admin-only read model; Telegram Stars Rating wire fields stay unset pending a dedicated official-semantics implementation. Reviewed-Head: 2796345775ea0f908fb7734601e5e1dee4b653b9 Original-Head: fa082b892fd5180c9c9bc53c81c21cf5d250a75b Co-authored-by: Egor Egorov <business.egor.sg@gmail.com>
This commit is contained in:
parent
b0fd3976f1
commit
fff8de783a
169 changed files with 55769 additions and 282 deletions
97
internal/store/bot_verification.go
Normal file
97
internal/store/bot_verification.go
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
)
|
||||
|
||||
// BotVerificationStore owns third-party verification: the icon catalogue, verifier
|
||||
// status, the granted marks and the application queue in front of them.
|
||||
//
|
||||
// Reads on the projection path (PeerVerification / PeerVerificationBatch) are on
|
||||
// every peer serialisation, so they must be cheap. The wire model carries one
|
||||
// BotVerification, and the store therefore permits exactly one mark per peer.
|
||||
type BotVerificationStore interface {
|
||||
// --- icon catalogue ---
|
||||
|
||||
// UpsertVerificationIcon adds or updates a catalogue entry by document id.
|
||||
UpsertVerificationIcon(ctx context.Context, icon domain.VerificationIcon) (domain.VerificationIcon, error)
|
||||
// SetVerificationIconActive retires or restores an entry. Marks already granted
|
||||
// with it keep rendering: the icon id is denormalised onto the mark.
|
||||
SetVerificationIconActive(ctx context.Context, iconID int64, active bool) (domain.VerificationIcon, error)
|
||||
// VerificationIcon reads one entry by id.
|
||||
VerificationIcon(ctx context.Context, iconID int64) (domain.VerificationIcon, error)
|
||||
// VerificationIconByDocument reads one entry by its custom emoji document id.
|
||||
VerificationIconByDocument(ctx context.Context, documentID int64) (domain.VerificationIcon, error)
|
||||
// ListVerificationIcons lists the catalogue, newest first.
|
||||
ListVerificationIcons(ctx context.Context, activeOnly bool, limit int) ([]domain.VerificationIcon, error)
|
||||
|
||||
// --- verifier status ---
|
||||
|
||||
// UpsertBotVerifierSettings grants or updates verifier status. Optimistic
|
||||
// locking on the stored version keeps two operators from clobbering each other.
|
||||
UpsertBotVerifierSettings(ctx context.Context, settings domain.BotVerifierSettings) (domain.BotVerifierSettings, error)
|
||||
// SetBotVerifierEnabled flips the operator kill switch. Existing marks stay,
|
||||
// but the verifier can grant nothing new and its settings stop being projected.
|
||||
SetBotVerifierEnabled(ctx context.Context, botID int64, enabled bool) (domain.BotVerifierSettings, error)
|
||||
// DeleteBotVerifierSettings removes verifier status; its marks cascade away with
|
||||
// it, because a mark whose verifier no longer exists has nothing to render.
|
||||
DeleteBotVerifierSettings(ctx context.Context, botID int64) (bool, error)
|
||||
// BotVerifierSettings reads one verifier's status, enabled or not.
|
||||
BotVerifierSettings(ctx context.Context, botID int64) (domain.BotVerifierSettings, error)
|
||||
// BotVerifierSettingsBatch resolves several bots in one round trip for the
|
||||
// botInfo projection; bots without verifier status are absent from the map.
|
||||
BotVerifierSettingsBatch(ctx context.Context, botIDs []int64) (map[int64]domain.BotVerifierSettings, error)
|
||||
// ListBotVerifiers lists verifier bots for the admin panel.
|
||||
ListBotVerifiers(ctx context.Context, enabledOnly bool, limit int) ([]domain.BotVerifierSettings, error)
|
||||
|
||||
// --- granted marks ---
|
||||
|
||||
// GrantCustomVerification creates or updates the peer's mark. A different
|
||||
// verifier replaces the current mark rather than leaving hidden fallback state.
|
||||
// The icon is taken from the verifier's settings at grant time and the caller
|
||||
// has already resolved the description through
|
||||
// domain.BotVerifierSettings.DescriptionFor.
|
||||
GrantCustomVerification(ctx context.Context, mark domain.CustomVerification) (domain.CustomVerification, bool, error)
|
||||
// RevokeCustomVerification removes this verifier's mark from the peer and
|
||||
// reports whether anything was removed, so a repeated revoke is a no-op.
|
||||
RevokeCustomVerification(ctx context.Context, verifierBotID int64, peer domain.Peer) (bool, error)
|
||||
// CustomVerification reads one verifier's mark on a peer.
|
||||
CustomVerification(ctx context.Context, verifierBotID int64, peer domain.Peer) (domain.CustomVerification, error)
|
||||
// PeerVerification returns the peer's single mark. Missing marks report
|
||||
// domain.ErrCustomVerificationNotFound.
|
||||
PeerVerification(ctx context.Context, peer domain.Peer) (domain.CustomVerification, error)
|
||||
// PeerVerificationBatch resolves the projection for many peers at once. This is
|
||||
// the call on the hot serialisation path, so peers without a mark are simply
|
||||
// absent instead of erroring.
|
||||
PeerVerificationBatch(ctx context.Context, peers []domain.Peer) (map[domain.Peer]domain.CustomVerification, error)
|
||||
// CountCustomVerifications reports how many peers a verifier has marked, for the
|
||||
// per-verifier bound.
|
||||
CountCustomVerifications(ctx context.Context, verifierBotID int64) (int, error)
|
||||
// ListCustomVerifications is the admin listing query with keyset paging.
|
||||
ListCustomVerifications(ctx context.Context, filter domain.CustomVerificationFilter) ([]domain.CustomVerification, error)
|
||||
|
||||
// --- application queue ---
|
||||
|
||||
// CreateCustomVerificationRequest files an application. A pending application on
|
||||
// the same (verifier, peer) reports domain.ErrCustomVerificationRequestExists.
|
||||
CreateCustomVerificationRequest(ctx context.Context, req domain.CustomVerificationRequest) (domain.CustomVerificationRequest, error)
|
||||
// DecideCustomVerificationRequest moves an application through its status
|
||||
// machine. approve=true grants the mark in the same transaction through the
|
||||
// supplied callback, so an approved application can never exist without its
|
||||
// mark; revoke removes it the same way.
|
||||
DecideCustomVerificationRequest(ctx context.Context, requestID int64, version int64, status domain.CustomVerificationRequestStatus, decidedBy, reason, note string, apply func(ctx context.Context, req domain.CustomVerificationRequest) error) (domain.CustomVerificationRequest, bool, error)
|
||||
// CustomVerificationRequest reads one application.
|
||||
CustomVerificationRequest(ctx context.Context, requestID int64) (domain.CustomVerificationRequest, error)
|
||||
// PendingCustomVerificationRequest returns the live application for a
|
||||
// (verifier, peer) pair, if any.
|
||||
PendingCustomVerificationRequest(ctx context.Context, verifierBotID int64, peer domain.Peer) (domain.CustomVerificationRequest, error)
|
||||
// ListCustomVerificationRequests is the review-queue query with keyset paging.
|
||||
ListCustomVerificationRequests(ctx context.Context, filter domain.CustomVerificationRequestFilter) ([]domain.CustomVerificationRequest, error)
|
||||
// CustomVerificationRequestsForApplicant returns an applicant's own history for
|
||||
// the verifier bot's /status command.
|
||||
CustomVerificationRequestsForApplicant(ctx context.Context, applicantUserID int64, limit int) ([]domain.CustomVerificationRequest, error)
|
||||
// CustomVerificationRequestCounts is the queue summary by status.
|
||||
CustomVerificationRequestCounts(ctx context.Context) (map[domain.CustomVerificationRequestStatus]int64, error)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue