4.6 KiB
Relay trust bootstrap
This document describes how js/services/trustBootstrap.js seeds trusted relays/actors for moderation, how it waits for relay availability, and how the relay list and admin lists are refreshed.
Overview
bootstrapTrustedSeeds() is a lightweight bootstrapping step that:
- Waits briefly for admin list hydration and relay readiness.
- Builds a trusted seed set from admin configuration and defaults.
- Hands that trusted seed set to
moderationServiceso trusted reports, mutes, and summary stats are computed consistently. - Re-runs when admin/editor lists change.
Configuration inputs
Trusted seed inputs are pulled from configuration and feature flags:
FEATURE_TRUST_SEEDS(flag injs/constants.js): gates whether bootstrapping runs at all.ADMIN_SUPER_NPUB(fromconfig/instance-config.jsviajs/config.js): always included when set.accessControl.getEditors()(fromjs/accessControl.js): editor list sourced from admin lists or defaults.DEFAULT_TRUST_SEED_NPUBS(fromconfig/instance-config.jsviajs/constants.js): used only if there are no super/admin seeds.
Seed selection and trust computation
buildTrustedSeeds() composes a Set of Nostr npub identifiers in this order:
- Add the super admin (
ADMIN_SUPER_NPUB). - Add editor npubs (
accessControl.getEditors()). - If no seeds exist yet, fall back to
DEFAULT_TRUST_SEED_NPUBS.
The resulting Set is passed to moderationService.setTrustedSeeds(seeds).
moderationService uses these seeds as the baseline for trusted contacts and downstream trust calculations (trusted report counts, trusted mute lists, etc.), and recomputeAllSummaries() is called immediately after applying seeds so moderation views reflect the updated trust graph.
Relay readiness and fallback behavior
Bootstrapping is intentionally defensive so the UI can initialize quickly:
- Access control hydration:
waitForAccessControl()racesaccessControl.ensureReady()against a 3.5s timeout. If hydration times out, bootstrapping logs a dev warning and falls back to defaults. - Immediate apply: Seeds are applied immediately after the first hydration attempt, even if the admin list hydration failed, so moderation does not block on relay availability.
- Retry when relays are ready: If hydration failed,
bootstrapTrustedSeeds()checks for relay readiness vianostrService.nostrClient.relays(and pool existence). If relays become available within 3.5s, it retries admin list hydration once. If relays never become ready, it logs a dev warning and re-applies the current seeds to keep moderation functional. - Change listeners:
accessControl.onEditorsChange()andaccessControl.onBlacklistChange()are registered so changes affecting the moderator roster or eligibility re-run seed application and recompute moderation summaries. Creator-whitelist changes do not affect trust seeds.
Relay list persistence and refresh
trustBootstrap does not persist or update relay lists itself. Instead it relies on the shared Nostr client state maintained by the relay manager and access control:
- Relay list loading:
js/relayManager.jsloads a profile’s relay list from NIP-65 (kind10002) events, normalizes relay URLs, and falls back toDEFAULT_RELAY_URLSif nothing is found or the pool is unavailable. The relay manager updates the activenostrClientrelay list in memory vianostrClient.applyRelayPreferences()(or by assigning tonostrClient.relays). - Relay list refresh: Relay list changes are published to relays via
relayManager.publishRelayList()and reloaded during profile refresh flows, which updatesnostrClient.relaysthattrustBootstraplater observes. - Admin list persistence:
js/accessControl.jshydrates admin/editor lists from cached state injs/adminListStore.js(local storage). It then refreshes from relay-backed admin lists whenensureReady()is called. The cache ensuresbootstrapTrustedSeeds()can use stored admin lists before relays are available.
Data flow summary
config/instance-config.js
└─> js/config.js -> js/constants.js (FEATURE_TRUST_SEEDS, DEFAULT_TRUST_SEED_NPUBS)
└─> js/services/trustBootstrap.js
├─> accessControl.ensureReady() (admin lists + cache)
├─> nostrService.nostrClient.relays (relay readiness)
└─> moderationService.setTrustedSeeds() + recomputeAllSummaries()
When the relay list or admin lists change, accessControl refreshes from cache/relays and the trust bootstrapper re-applies seeds so moderation stays up to date.