Documentation
¶
Index ¶
- Variables
- func AddAdminBlockedIP(ipOrCIDR string) error
- func AddKindToWhitelist(kind int) error
- func AddPubkeyToWhitelist(pubkey string) error
- func AddToPermanentBlacklist(pubkey string) error
- func AddToTemporaryBlacklist(pubkey string, blacklistConfig cfgType.BlacklistConfig) error
- func AdminMutelistPubkeys() []string
- func AtomicWriteFile(path string, data []byte, perm os.FileMode) error
- func CheckAndMigrateConfig(filename string) error
- func CheckBlacklistCached(pubkey, eventContent string) (bool, string)
- func CheckWhitelistCached(evt nostr.Event) (bool, string)
- func ClearTemporaryBans()
- func ConfigPath(filename string) string
- func EnsureAllConfigFiles() error
- func FetchAuthorMuteListEvents(author string) ([]*nostr.Event, error)
- func FetchGroupedMuteListPubkeys(authors []string) (map[string][]string, error)
- func GetAdminMutelistPubkeysFor(adminPubkey string) []string
- func GetBlacklistConfig() *cfgType.BlacklistConfig
- func GetBlockedIPs() []string
- func GetConfig() *cfgType.ServerConfig
- func GetDataDir() string
- func GetTemporaryBlacklist() []map[string]interface{}
- func GetWhitelistConfig() *cfgType.WhitelistConfig
- func InitializePubkeyCache(ctx context.Context)
- func IsDMProtectedKind(kind int) bool
- func IsIPBlocked(ip string) (bool, string)
- func IsKindWhitelisted(kind int) bool
- func IsPubKeyWhitelistedCached(pubKey string, skipEnabledCheck bool) bool
- func LoadAdminMutelist()
- func LoadBlacklistConfig(filename string) (*cfgType.BlacklistConfig, error)
- func LoadConfig(filename string) (*cfgType.ServerConfig, error)
- func LoadIPBlocklist(cfg cfgType.BlacklistConfig)
- func LoadWhitelistConfig(filename string) (*cfgType.WhitelistConfig, error)
- func ParsePermanentIPPrefixes(entries []string) []netip.Prefix
- func RecordIPRateViolation(ip string, cfg cfgType.BlacklistConfig)
- func RemoveAdminBlockedIP(ipOrCIDR string) error
- func RemoveFromPermanentBlacklist(pubkey string) error
- func RemoveKindFromWhitelist(kind int) error
- func RemovePubkeyFromWhitelist(pubkey string) error
- func ResetAdminMutelistForTest()
- func ResetBlacklistConfig()
- func ResetConfig()
- func ResetIPBlocklistForTest()
- func ResetWhitelistConfig()
- func SetConfigForTesting(c *cfgType.ServerConfig)
- func SetDataDir(dir string)
- func SetEmbeddedExamples(fs embed.FS)
- func SetRateLimit(cfg *cfgType.ServerConfig)
- func SetResourceLimit(cfg *cfgType.ResourceLimits)
- func SetSizeLimit(cfg *cfgType.ServerConfig)
- func SetTriggerRestart(fn func())
- func SizeLimit(sl *SizeLimiter)
- func StartIPBlocklistSweeper(ctx context.Context)
- func SuppressWatcherFor(path string)
- func SweepExpiredIPTempBans()
- func TriggerRestart()
- func UpdateAuthConfig(au cfgType.AuthConfig) error
- func UpdateBackupRelayConfig(br cfgType.BackupRelayConfig) error
- func UpdateBlacklistConfig(cfg cfgType.BlacklistConfig) error
- func UpdateEventPurgeConfig(ep cfgType.EventPurgeConfig) error
- func UpdateEventTimeConstraints(etc cfgType.EventTimeConstraints) error
- func UpdateLoggingConfig(lg cfgType.LogConfig) error
- func UpdateRateLimitConfig(rl cfgType.RateLimitConfig) error
- func UpdateResourceLimits(rl cfgType.ResourceLimits) error
- func UpdateServerConfig(srv cfgType.ServerSettings) error
- func UpdateWhitelistConfig(cfg cfgType.WhitelistConfig) error
- func ValidateAndApplyDefaults(cfg *cfgType.ServerConfig) (warnings []string, err error)
- func WatchConfigFile(filePath string, restartChan chan<- struct{})
- type AdminMutelistMeta
- type CategoryLimiter
- type KindLimiter
- type PubkeyCache
- func (pc *PubkeyCache) GetBlacklistedPubkeys() []string
- func (pc *PubkeyCache) GetDirectWhitelistedPubkeys() []string
- func (pc *PubkeyCache) GetDomainPubkeys(domain string) []string
- func (pc *PubkeyCache) GetGroupedMutelist() map[string][]string
- func (pc *PubkeyCache) GetPubkeyCacheStats() map[string]interface{}
- func (pc *PubkeyCache) GetWhitelistSourceBreakdown() map[string]interface{}
- func (pc *PubkeyCache) GetWhitelistedPubkeys() []string
- func (pc *PubkeyCache) IsBlacklisted(pubkey string) bool
- func (pc *PubkeyCache) IsBlacklistedForValidation(pubkey string) bool
- func (pc *PubkeyCache) IsWhitelisted(pubkey string) bool
- func (pc *PubkeyCache) IsWhitelistedForValidation(pubkey string) bool
- func (pc *PubkeyCache) RefreshBlacklist() error
- func (pc *PubkeyCache) RefreshWhitelist() error
- type RateLimiter
- func (rl *RateLimiter) AddCategoryLimit(category string, limit rate.Limit, burst int)
- func (rl *RateLimiter) AddKindLimit(kind int, limit rate.Limit, burst int)
- func (rl *RateLimiter) AllowEvent(kind int, category string) (bool, string)
- func (rl *RateLimiter) AllowReq() (bool, string)
- func (rl *RateLimiter) AllowWs() (bool, string)
- type SizeLimiter
Constants ¶
This section is empty.
Variables ¶
var ConfigMu sync.Mutex
ConfigMu serializes admin writes across the whole config package. Public so write helpers in config/Blacklist.go, config/Whitelist.go, config/IPBlacklist.go and server/utils/loadRelayMetadata.go can all share one critical section.
Functions ¶
func AddAdminBlockedIP ¶ added in v0.7.0
AddAdminBlockedIP adds an IP or CIDR to config.yml's blacklist.permanent_blocked_ips — the admin-curated source — distinct from the auto-escalation path which writes to the ip_bans.json sidecar. Used by NIP-86 `blockip`.
Important quirk: the BlacklistConfig type has a PermanentBlockedIPs field but the *production* IP enforcement reads its initial state from cfg.Blacklist (loaded from config.yml), not from blacklist.yml. So admin writes funnel through ServerConfig rather than the standalone blacklist file.
The canonicalized form (via parseIPOrCIDR) is stored, so callers can pass either "1.2.3.4" or "1.2.3.4/32" or " 1.2.3.4 " and get consistent storage. After saving config.yml the in-memory IP blocklist is rebuilt via LoadIPBlocklist so the next IsIPBlocked call sees the new entry.
Idempotent: returns nil with an info log if the prefix is already in the admin list.
func AddKindToWhitelist ¶ added in v0.7.0
AddKindToWhitelist appends kind to whitelist.yml's kind_whitelist.kinds. Used by NIP-86 `allowkind`. The yaml field is `[]string` so older operator-edited configs that store kind labels or ranges still parse; this helper stores ints via strconv.Itoa. Idempotent.
func AddPubkeyToWhitelist ¶ added in v0.7.0
AddPubkeyToWhitelist appends pubkey to whitelist.yml's pubkey_whitelist.pubkeys. Used by NIP-86 `allowpubkey`. The configured set is grain's "elevated users" registry regardless of whether the whitelist is currently enabled — see the [[project-whitelist-semantics]] note.
Caller doesn't need to acquire ConfigMu; this function does it internally. Idempotent: returns nil with an info log if the pubkey is already in either the hex or npub list.
func AddToPermanentBlacklist ¶
AddToPermanentBlacklist appends pubkey to blacklist.yml's permanent_blacklist_pubkeys. Called from both the auto-escalation path (temp-ban → permanent after threshold) and the NIP-86 banpubkey method. Idempotent: returns an error sentinel rather than silently re-adding.
Takes ConfigMu for the duration of the read-modify-write to keep concurrent admin calls from clobbering each other. The save helper does the watcher-suppression + atomic file write + in-memory state reload; callers don't need to remember those.
func AddToTemporaryBlacklist ¶
func AddToTemporaryBlacklist(pubkey string, blacklistConfig cfgType.BlacklistConfig) error
Adds a pubkey to the temporary blacklist
func AdminMutelistPubkeys ¶ added in v0.7.0
func AdminMutelistPubkeys() []string
AdminMutelistPubkeys returns the deduplicated union of every admin's synced pubkeys. This is the fourth blacklist source consumed by RefreshBlacklist.
func AtomicWriteFile ¶ added in v0.7.0
AtomicWriteFile writes data to a temp file in the same directory as `path` and then renames it into place. Atomic on POSIX and Windows when the target is a regular file on a writable filesystem.
Bind-mount fallback: when `path` is bind-mounted as an individual file (Docker, podman, Kubernetes ConfigMap projections), the host kernel refuses `rename` over it with EBUSY because the mount holds the inode. The pragmatic fallback is "if rename fails for any reason, try a truncating in-place write instead" — loses atomicity in those environments but admin writes still land.
Exported so server/utils can install it as the relay-metadata write hook (see startup.go) without an import cycle.
func CheckAndMigrateConfig ¶ added in v0.5.0
CheckAndMigrateConfig reads the raw YAML file and checks for outdated config formats (e.g., the old mongodb section from before the nostrdb migration). It prints warnings to stderr since this runs before loggers are initialized.
func CheckBlacklistCached ¶
CheckBlacklistCached uses cached pubkey lists and respects enabled state for validation
func CheckWhitelistCached ¶
CheckWhitelistCached uses cached pubkey lists and respects enabled state for validation
func ClearTemporaryBans ¶
func ClearTemporaryBans()
func ConfigPath ¶ added in v0.5.0
ConfigPath returns the full path for a file within the data directory.
func EnsureAllConfigFiles ¶ added in v0.4.1
func EnsureAllConfigFiles() error
EnsureAllConfigFiles creates all default config files from embedded examples if they don't exist. Files are created in the resolved data directory.
func FetchAuthorMuteListEvents ¶ added in v0.7.0
FetchAuthorMuteListEvents returns the winning (latest-per-kind/d) raw mute list events for a single author — including the encrypted `.content` that FetchGroupedMuteListPubkeys discards. It powers the admin private-mutelist sync (#60): the relay can fetch the owner's kind:10000 + kind:30000(d:"mute") events but can't decrypt them, so it hands the raw events to the owner's browser, which decrypts `.content` with the owner's signer and posts the resulting pubkeys back.
Reuses the same outbox-resolution + subscription path as the public-tag fetch; the only difference is it stops before extractMuteListPubkeys so the caller sees full events.
func FetchGroupedMuteListPubkeys ¶ added in v0.4.1
FetchGroupedMuteListPubkeys returns public `p`-tag pubkeys from each configured author's NIP-51 mute list events, grouped by author pubkey.
For each author, the fetch path is:
- Look up the author's NIP-65 mailbox list (kind:10002) via the client library's connected index relays.
- Target their outbox relays (write + both). If none are published or reachable, fall back to the relay's configured default client relays.
- Subscribe for kinds 10000 and 30000 from that author.
- Keep only the latest event per (kind, d-tag) — replaceable/addressable semantics — and for kind 30000 require `d:"mute"` (filtered here because the client library's Filter type does not currently serialize NIP-01 `#<tag>` tag filters in the REQ wire format).
- Extract public `p`-tag pubkeys from the winning events.
Encrypted `.content` entries (NIP-44 primarily, NIP-04 fallback per NIP-51) are not decrypted by the relay — only public tag entries are applied.
func GetAdminMutelistPubkeysFor ¶ added in v0.7.0
GetAdminMutelistPubkeysFor returns a copy of one admin's stored pubkeys, sorted. Used by the owner-only admin panel to render the synced keys with profiles — safe there because the dashboard is gated to the relay owner, unlike the public keys endpoint which only ever sees a count.
func GetBlacklistConfig ¶
func GetBlacklistConfig() *cfgType.BlacklistConfig
GetBlacklistConfig returns the blacklist configuration.
func GetBlockedIPs ¶ added in v0.7.0
func GetBlockedIPs() []string
GetBlockedIPs returns the merged list of permanent CIDRs (admin-curated from blacklist.yml plus auto-escalated entries from the sidecar) as canonical strings. Single-host bans render as bare IPs ("1.2.3.4" rather than "1.2.3.4/32") because that's how operators tend to type them. Order is not guaranteed; callers that care should sort.
Used by NIP-86's `listblockedips` — read-only, never returns nil.
func GetDataDir ¶ added in v0.5.0
func GetDataDir() string
GetDataDir returns the resolved data directory path.
func GetTemporaryBlacklist ¶
func GetTemporaryBlacklist() []map[string]interface{}
GetTemporaryBlacklist fetches all currently active temporary bans
func GetWhitelistConfig ¶
func GetWhitelistConfig() *cfgType.WhitelistConfig
GetWhitelistConfig returns the whitelist configuration.
func InitializePubkeyCache ¶
InitializePubkeyCache starts the cache system with initial refresh and background updates. ctx bounds the background refresh goroutines to the lifetime of the server instance that started them — on a config-reload restart the previous instance's refreshers are cancelled instead of accumulating (see #93).
func IsDMProtectedKind ¶ added in v0.7.0
IsDMProtectedKind reports whether events of this kind may be served only to the AUTHed p-tagged recipient. See the package var for rationale.
func IsIPBlocked ¶ added in v0.5.4
IsIPBlocked returns (true, reason) if the given IP string matches any permanent CIDR or has an active temp ban. The reason is suitable for log attribution.
func IsPubKeyWhitelistedCached ¶
IsPubKeyWhitelistedCached for purging operations - always uses cache regardless of enabled state
func LoadAdminMutelist ¶ added in v0.7.0
func LoadAdminMutelist()
LoadAdminMutelist reads the sidecar into memory. Safe to call before the DB is up; call once at startup after SetDataDir. A missing file is not an error — it just means no admin has synced yet.
func LoadBlacklistConfig ¶
func LoadBlacklistConfig(filename string) (*cfgType.BlacklistConfig, error)
LoadBlacklistConfig loads the blacklist configuration from blacklist.yml.
func LoadConfig ¶
func LoadConfig(filename string) (*cfgType.ServerConfig, error)
Update your LoadConfig function to call this:
func LoadIPBlocklist ¶ added in v0.5.4
func LoadIPBlocklist(cfg cfgType.BlacklistConfig)
LoadIPBlocklist initialises the in-memory permanent prefix list from the admin-curated config and the on-disk sidecar. Safe to call multiple times — subsequent calls replace the in-memory state. Should be called once at startup, after SetDataDir.
func LoadWhitelistConfig ¶
func LoadWhitelistConfig(filename string) (*cfgType.WhitelistConfig, error)
LoadWhitelistConfig loads the whitelist configuration from whitelist.yml.
func ParsePermanentIPPrefixes ¶ added in v0.5.4
ParsePermanentIPPrefixes converts a slice of strings (CIDRs or bare IPs) into netip.Prefix values. Invalid entries are skipped with a WARN log. A bare IP becomes a /32 (IPv4) or /128 (IPv6) prefix.
func RecordIPRateViolation ¶ added in v0.5.4
func RecordIPRateViolation(ip string, cfg cfgType.BlacklistConfig)
RecordIPRateViolation is the auto-escalation hook. The connection rate limiter calls this on every per-IP rate-limit rejection. Behaviour depends on cfg.IPRateViolationThreshold and IPMaxTempBans: when violations cross the threshold a temp ban is issued; once temp bans for that IP exceed the max, the IP is promoted to permanent and persisted to the sidecar.
All thresholds <= 0 disable the corresponding stage. With everything at 0 this function is a no-op and the IP escalation pipeline is off.
func RemoveAdminBlockedIP ¶ added in v0.7.0
RemoveAdminBlockedIP removes a matching prefix from config.yml's blacklist.permanent_blocked_ips. Does NOT touch the sidecar (auto-escalated bans) — those have their own lifecycle. Idempotent.
func RemoveFromPermanentBlacklist ¶ added in v0.7.0
RemoveFromPermanentBlacklist removes pubkey from blacklist.yml's permanent_blacklist_pubkeys AND permanent_blacklist_npubs (the npub list is matched by decoding each entry and comparing the resulting hex). Idempotent: removing a pubkey that isn't there returns nil with an info log.
func RemoveKindFromWhitelist ¶ added in v0.7.0
RemoveKindFromWhitelist removes any entry that parses to the given kind. Used by NIP-86 `disallowkind`. Idempotent.
func RemovePubkeyFromWhitelist ¶ added in v0.7.0
RemovePubkeyFromWhitelist removes pubkey from both pubkey_whitelist.pubkeys and pubkey_whitelist.npubs (decoded npubs matched against the supplied hex). Used by NIP-86 `unallowpubkey`. Idempotent — removing a pubkey that isn't there is a no-op.
func ResetAdminMutelistForTest ¶ added in v0.7.0
func ResetAdminMutelistForTest()
ResetAdminMutelistForTest clears in-memory admin mutelist state. Tests only.
func ResetBlacklistConfig ¶
func ResetBlacklistConfig()
ResetBlacklistConfig clears the existing blacklist configuration.
func ResetIPBlocklistForTest ¶ added in v0.5.4
func ResetIPBlocklistForTest()
ResetIPBlocklistForTest clears all in-memory IP-blocklist state. Tests only — production code paths use LoadIPBlocklist.
func ResetWhitelistConfig ¶
func ResetWhitelistConfig()
ResetWhitelistConfig clears the existing whitelist configuration.
func SetConfigForTesting ¶ added in v0.7.0
func SetConfigForTesting(c *cfgType.ServerConfig)
SetConfigForTesting injects a server configuration without going through the YAML loader. Reserved for tests that need to exercise behavior gated on specific config values (e.g. auth.relay_url_match in the NIP-98 path) without writing a fixture file. Production code should never call this — there is no mutex held across the swap, so concurrent readers may observe the new value at any moment.
func SetDataDir ¶ added in v0.5.0
func SetDataDir(dir string)
SetDataDir sets the resolved data directory path for the application.
func SetEmbeddedExamples ¶ added in v0.4.1
SetEmbeddedExamples sets the embedded filesystem from main package
func SetRateLimit ¶
func SetRateLimit(cfg *cfgType.ServerConfig)
SetRateLimit stores the rate limit configuration for later per-client use.
func SetResourceLimit ¶
func SetResourceLimit(cfg *cfgType.ResourceLimits)
func SetSizeLimit ¶
func SetSizeLimit(cfg *cfgType.ServerConfig)
func SetTriggerRestart ¶ added in v0.7.0
func SetTriggerRestart(fn func())
SetTriggerRestart installs the hook that pushes a value onto the restart channel. server/startup.go wires the real implementation once that channel exists.
func SizeLimit ¶
func SizeLimit(sl *SizeLimiter)
func StartIPBlocklistSweeper ¶ added in v0.5.4
StartIPBlocklistSweeper kicks off the background goroutine that expires temp bans every minute. The goroutine exits when ctx is cancelled, so it's called once per server instance and the previous instance's sweeper stops cleanly on a config-reload restart (see #93).
func SuppressWatcherFor ¶ added in v0.7.0
func SuppressWatcherFor(path string)
SuppressWatcherFor blocks fsnotify-driven restarts for `path` for the next suppressWindow. Path is normalized with filepath.Clean so callers and the watcher always compare on the same key.
func SweepExpiredIPTempBans ¶ added in v0.5.4
func SweepExpiredIPTempBans()
SweepExpiredIPTempBans removes temp ban entries past their unbanTime. Caller is expected to schedule this periodically; see StartIPBlocklistSweeper for the canonical loop.
func TriggerRestart ¶ added in v0.7.0
func TriggerRestart()
TriggerRestart asks the server to restart through the existing loop in server/startup.go. The HTTP response to whoever called this has already returned by the time the restart fires — fsnotify-suppressed admin writes mean only an explicit call kicks the restart, which is the whole point of staging config updates.
func UpdateAuthConfig ¶ added in v0.7.0
func UpdateAuthConfig(au cfgType.AuthConfig) error
UpdateAuthConfig stages auth settings (required flag, relay_url, relay_url_match mode). The validation that consults these reads from GetConfig().Auth on each AUTH event, so the in-memory swap makes new sessions see the new policy without restart. Existing authenticated WS connections retain their session, which matches operator intent (don't kick logged-in users for a policy tweak).
Hard validation: when Required is true, RelayURL must be set — the NIP-42 challenge's `relay` tag is what clients echo back, and an empty URL means every signed AUTH event would be rejected. We reject the write here rather than wait for the post-reload AUTH flood that would lock every client out of a "public" relay.
func UpdateBackupRelayConfig ¶ added in v0.7.0
func UpdateBackupRelayConfig(br cfgType.BackupRelayConfig) error
UpdateBackupRelayConfig stages the backup-relay forwarding settings. The backup-relay goroutine reads these at startup; a reload reinitializes it.
Hard validation: when Enabled is true, URLs must be non-empty and every entry must be a WebSocket URL (ws:// or wss://). SendToBackupRelay does a websocket.Dial per URL and will log + return an error every event if any URL is malformed; we reject the write up-front so the operator finds out at save time, not in a flood of relay logs.
func UpdateBlacklistConfig ¶ added in v0.7.0
func UpdateBlacklistConfig(cfg cfgType.BlacklistConfig) error
UpdateBlacklistConfig stages the standalone blacklist.yml — the pubkey/npub/word/mutelist surface — and also persists the IP SCALARS (max-temp-bans, durations, thresholds) to config.yml's blacklist: section so the dashboard can edit them via the same bulk save. The IP LIST (PermanentBlockedIPs) is preserved from the live in-memory state: it has its own granular write path via blockip / unblockip, and round-tripping the list through the bulk save would race against per-IP edits.
Cross-file write rationale: BlacklistConfig is dual-source — the type is one struct but two files own different slices of it ([[project-blacklist-dual-source]]). UpdateBlacklistConfig has always written blacklist.yml; this commit extends it to also write the IP scalars to config.yml so the admin dashboard's "Save" affordance covers the full operator-tunable surface.
func UpdateEventPurgeConfig ¶ added in v0.7.0
func UpdateEventPurgeConfig(ep cfgType.EventPurgeConfig) error
UpdateEventPurgeConfig stages a new event-purge configuration. Purge timers stay on the old schedule until reload.
func UpdateEventTimeConstraints ¶ added in v0.7.0
func UpdateEventTimeConstraints(etc cfgType.EventTimeConstraints) error
UpdateEventTimeConstraints stages the min/max created_at window. The validator reads from GetConfig() per event, so this is effectively live.
Rejects relative-time strings that won't parse. The validator silently falls back to a default when its time.ParseDuration call fails, so a typo like "now-5moo" would otherwise "save" but quietly behave as if unset — surprising for the operator. We validate here so the form shows the error before the bad value hits disk.
func UpdateLoggingConfig ¶ added in v0.7.0
UpdateLoggingConfig stages logging settings. The existing slog handlers keep writing to the old file/level until reload — rebuilding the logging tree mid-run is fiddly and not worth the complexity given reload exists.
func UpdateRateLimitConfig ¶ added in v0.7.0
func UpdateRateLimitConfig(rl cfgType.RateLimitConfig) error
UpdateRateLimitConfig stages a new rate-limit configuration: the supplied blob replaces the current cfg.RateLimit and config.yml is rewritten. Running rate limiters keep their buckets until the next reload (grain_reloadconfig); reads of cfg via GetConfig() see the new section immediately.
func UpdateResourceLimits ¶ added in v0.7.0
func UpdateResourceLimits(rl cfgType.ResourceLimits) error
UpdateResourceLimits stages CPU/memory caps. The runtime/debug hooks (GOMAXPROCS, soft memory limit) are applied at startup; reload reapplies them.
func UpdateServerConfig ¶ added in v0.7.0
func UpdateServerConfig(srv cfgType.ServerSettings) error
UpdateServerConfig stages the HTTP server block (timeouts, connection caps, max subscriptions). Timeouts on the running http.Server can't be changed in place; reload picks up new values.
func UpdateWhitelistConfig ¶ added in v0.7.0
func UpdateWhitelistConfig(cfg cfgType.WhitelistConfig) error
UpdateWhitelistConfig stages the whole whitelist (enabled flags, cache refresh intervals, pubkeys, npubs, kinds, domains). Used by NIP-86's grain_updatewhitelistconfig — the dashboard fetches the current config via GET /api/v1/relay/config/whitelist, lets the operator edit it, then POSTs the full struct back through here. Cache is refreshed in-place so reads see the new state immediately; reload is only needed for changes that affect background goroutines (refresh intervals).
func ValidateAndApplyDefaults ¶ added in v0.5.0
func ValidateAndApplyDefaults(cfg *cfgType.ServerConfig) (warnings []string, err error)
ValidateAndApplyDefaults checks the config for zero-valued fields and applies sensible defaults. It returns a list of warnings for each default applied and an error if the config is truly broken.
func WatchConfigFile ¶
func WatchConfigFile(filePath string, restartChan chan<- struct{})
Types ¶
type AdminMutelistMeta ¶ added in v0.7.0
AdminMutelistMeta is the per-admin summary the dashboard renders so the owner knows when they last synced and how many pubkeys they contributed.
func GetAdminMutelistMeta ¶ added in v0.7.0
func GetAdminMutelistMeta() []AdminMutelistMeta
GetAdminMutelistMeta returns the per-admin summary (count + last-synced) for dashboard display. Sorted by pubkey for stable rendering.
func SetAdminMutelist ¶ added in v0.7.0
func SetAdminMutelist(adminPubkey string, pubkeys []string) (AdminMutelistMeta, error)
SetAdminMutelist records the decrypted pubkey set an admin pushed via the sync endpoint, persists it to the sidecar, and refreshes the blacklist cache so the new entries take effect immediately. Pubkeys are lowercased, trimmed, validated as 64-char hex, and deduplicated before storage — callers may pass raw client input. Passing an empty set clears that admin's contribution (a deliberate "un-sync").
type CategoryLimiter ¶
type PubkeyCache ¶
type PubkeyCache struct {
// contains filtered or unexported fields
}
PubkeyCache manages cached pubkey lists with source tracking for whitelist and blacklist operations
func GetPubkeyCache ¶
func GetPubkeyCache() *PubkeyCache
GetPubkeyCache returns the global cache instance
func (*PubkeyCache) GetBlacklistedPubkeys ¶
func (pc *PubkeyCache) GetBlacklistedPubkeys() []string
func (*PubkeyCache) GetDirectWhitelistedPubkeys ¶ added in v0.4.1
func (pc *PubkeyCache) GetDirectWhitelistedPubkeys() []string
GetDirectWhitelistedPubkeys returns only direct config pubkeys (excluding domain pubkeys) Use this for API endpoints that want to show only directly configured pubkeys
func (*PubkeyCache) GetDomainPubkeys ¶ added in v0.4.1
func (pc *PubkeyCache) GetDomainPubkeys(domain string) []string
GetDomainPubkeys returns pubkeys for a specific domain from cache
func (*PubkeyCache) GetGroupedMutelist ¶ added in v0.5.0
func (pc *PubkeyCache) GetGroupedMutelist() map[string][]string
GetGroupedMutelist returns a snapshot of the most recently fetched per-author mutelist pubkey map. The returned map is a deep copy: callers can mutate it freely without touching cache state. Returns an empty map (never nil) when the cache hasn't been populated yet.
func (*PubkeyCache) GetPubkeyCacheStats ¶
func (pc *PubkeyCache) GetPubkeyCacheStats() map[string]interface{}
GetPubkeyCacheStats returns enhanced cache statistics for monitoring
func (*PubkeyCache) GetWhitelistSourceBreakdown ¶ added in v0.4.1
func (pc *PubkeyCache) GetWhitelistSourceBreakdown() map[string]interface{}
GetWhitelistSourceBreakdown returns detailed source breakdown for API endpoints
func (*PubkeyCache) GetWhitelistedPubkeys ¶
func (pc *PubkeyCache) GetWhitelistedPubkeys() []string
GetWhitelistedPubkeys returns a copy of all whitelisted pubkeys for bulk operations Maintains backward compatibility
func (*PubkeyCache) IsBlacklisted ¶
func (pc *PubkeyCache) IsBlacklisted(pubkey string) bool
Blacklist functions remain unchanged
func (*PubkeyCache) IsBlacklistedForValidation ¶
func (pc *PubkeyCache) IsBlacklistedForValidation(pubkey string) bool
func (*PubkeyCache) IsWhitelisted ¶
func (pc *PubkeyCache) IsWhitelisted(pubkey string) bool
IsWhitelisted checks if a pubkey is in ANY whitelist source (fast lookup) Maintains backward compatibility
func (*PubkeyCache) IsWhitelistedForValidation ¶
func (pc *PubkeyCache) IsWhitelistedForValidation(pubkey string) bool
IsWhitelistedForValidation checks if a pubkey is whitelisted AND whitelist is enabled Maintains backward compatibility
func (*PubkeyCache) RefreshBlacklist ¶
func (pc *PubkeyCache) RefreshBlacklist() error
Blacklist functions remain unchanged for backward compatibility
func (*PubkeyCache) RefreshWhitelist ¶
func (pc *PubkeyCache) RefreshWhitelist() error
RefreshWhitelist rebuilds the whitelist cache with source tracking Always caches all sources regardless of enabled state for sync/purge operations
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter holds per-client rate limiters. Each connected client gets its own instance so limits are enforced independently.
func NewClientRateLimiter ¶ added in v0.5.0
func NewClientRateLimiter() *RateLimiter
NewClientRateLimiter creates a fresh RateLimiter from the stored config. Called once per new client connection.
func (*RateLimiter) AddCategoryLimit ¶
func (rl *RateLimiter) AddCategoryLimit(category string, limit rate.Limit, burst int)
func (*RateLimiter) AddKindLimit ¶
func (rl *RateLimiter) AddKindLimit(kind int, limit rate.Limit, burst int)
func (*RateLimiter) AllowEvent ¶
func (rl *RateLimiter) AllowEvent(kind int, category string) (bool, string)
func (*RateLimiter) AllowReq ¶
func (rl *RateLimiter) AllowReq() (bool, string)
func (*RateLimiter) AllowWs ¶
func (rl *RateLimiter) AllowWs() (bool, string)
type SizeLimiter ¶
type SizeLimiter struct {
// contains filtered or unexported fields
}
func GetSizeLimiter ¶
func GetSizeLimiter() *SizeLimiter
func NewSizeLimiter ¶
func NewSizeLimiter(globalMaxSize int) *SizeLimiter
func (*SizeLimiter) AddKindSizeLimit ¶
func (sl *SizeLimiter) AddKindSizeLimit(kind int, maxSize int)
func (*SizeLimiter) SetGlobalMaxSize ¶
func (sl *SizeLimiter) SetGlobalMaxSize(maxSize int)