owpengram-server/internal/store/reserved_username.go
Astra 65aaa263b1 usernames: operator reserved-username blocklist
A plain blocklist for names like @support - separate from the collectible
system, so a reservation has no owner, no price and no "bought on Fragment"
badge.

- reserved_usernames table + migration.
- Enforced in replacePeerUsernameTx (the single editable-username write point:
  account.updateUsername, channels.updateUsername, @BotFather /setusername) and
  in the collectible mint path; a reserved name returns USERNAME_OCCUPIED.
- admin.Service: ReserveUsername / UnreserveUsername (journalled commands) and
  the ReservedUsernames listing.
- adminapi: /v1/reserved-usernames{,/reserve,/unreserve}.
- telesrv-admin panel + a "Reserved Usernames" page in the web UI (dist rebuilt).
- Postgres and in-memory store implementations; the memory registry gains an
  optional reserved-name check so tests exercise the same rule.
2026-09-09 19:57:14 +01:00

22 lines
971 B
Go

package store
import (
"context"
"telesrv/internal/domain"
)
// ReservedUsernameStore owns the operator username blocklist. IsReserved is the
// hot path consulted on every editable-username write; the rest are the admin
// lifecycle.
type ReservedUsernameStore interface {
// IsReserved reports whether usernameLower (already lowercased) is blocked.
IsReserved(ctx context.Context, usernameLower string) (bool, error)
// ReserveUsername adds an entry. Returns created=false if it already existed
// (the existing reason/actor are kept).
ReserveUsername(ctx context.Context, username, reason, actor string) (created bool, err error)
// UnreserveUsername removes an entry. Returns removed=false if absent.
UnreserveUsername(ctx context.Context, username string) (removed bool, err error)
// ReservedUsernames pages the blocklist, newest first.
ReservedUsernames(ctx context.Context, filter domain.ReservedUsernameFilter) ([]domain.ReservedUsername, error)
}