Skip to content

Documentation audit

Baseline and scope

September 20 master documentation update

Reviewed Relay master 9faf66dc and the published 0.11.2 assets. Installation uses the 0.11 minor channel; no 0.12 release is assumed. Post-release behavior is marked in the guides, including saved messages, multi-message sharing, guided moderation, theme imports, quiet hours, smart status filtering, diagnostics, metadata v3, history recovery, storage modules, and native desktop removal.

Evidence includes Relay's docs/saved-messages.md, docs/multi-message-sharing.md, docs/moderation.md, docs/theme-catalog.md, docs/metadata.md, docs/storage-modules.md, docs/pastebin.md, and docs/contributing.md, checked alongside Settings components, settings search routes, and history recovery code. Protocol references distinguish draft metadata from accepted account-extban support. Refactors and fixes without changed procedures are not feature callouts.

This update is source review and documentation build/link validation, not an application runtime audit. The runtime results below are historical and were not rerun for this update. No live IRC, database migration, notification delivery, or cross-platform client workflow was exercised.

Earlier runtime audit

This audit targets Relay b67fdde3dadc3feffef7f0aa92d2b425913495f9, replacing the earlier v0.11.0 baseline. The source still reports package version 0.11.0; that version string does not establish that later commits shipped in that release. In particular, optional TOTP/MFA (dafe0b7b), required-MFA persistence (c608bc44, 0d1ca15f) and the right-side mobile Settings drawer (eae6e514, merged at the audited commit) are later checkout behavior. Product releases remain owned by relayirc.com.

The scope is documentation accuracy and operational/user coverage, not an application refactor or comprehensive security review. Source paths below are relative to the Relay repository at that commit. The sibling checkout was read as evidence; generated client assets and local data belong only to a disposable /tmp/relay-docs-audit copy.

Guide-by-guide source review

Guide Implementation and relevant tests reviewed Finding/action
Overview package.json, commit history Identify commit baseline; keep product release ownership external
Installation Dockerfile, docker-entrypoint.sh, docker-relay.sh, cmd/relay/home.go UID/data mount behavior retained; distinguish YAML fallback from container legacy JavaScript detection
First administrator cmd/relay/users.go, start.go, internal/auth/manager.go, internal/session/auth_events.go, cmd/relay/cli_test.go Correct users add; document initialization and non-permanent token lifecycle
Client apps desktop/, client/components/Settings/General.vue, client/js/upload.ts Browser/PWA versus desktop upload boundary; external package listings retained
Development go.mod, package.json, vite.config.ts, internal/httpapi/mux.go Node 24+, Go 1.26.6+, npm ci, generated public/, watch and isolated listener
Settings client/js/settingsSearch.ts, client/components/Windows/Settings.vue Preserve topic anchors; add operational references and right drawer navigation
Server and users internal/session/admin_events.go, admin_config.go, client/components/Settings/AdminOperations.vue Browser reload differs from restart; restart exits 0 and requires supervisor
Storage and retention internal/config/defaults.yaml, cmd/relay/storage.go, internal/store/factory/, internal/store/cleaner/ Default SQLite plus text; per-account log gate; distinguish schema migrate from PostgreSQL import
Media and files internal/uploads/, internal/dcc/, internal/irchandlers/link.go, client/components/Settings/AdminOverview.vue KiB/hours/MiB units, upload and DCC prerequisites cross-linked
Authentication internal/session/mfa_events.go, admin_config.go, internal/auth/totp.go, oidc.go, mfa_events_test.go, webauthn_security_test.go Enrollment, optional/required MFA, remembered-session boundary and provider policy
Integrations and branding internal/session/admin_config.go, partyline.go, internal/shortlinks/, client/components/Settings/AdminIntegrations.vue Disabled integration defaults and asset fallback retained; external service delivery not exercised
Network gateways internal/config/load.go, webirc.go, internal/publicmode/, internal/httpapi/ Narrow proxy trust and complete deployment example
Public mode internal/publicmode/, internal/config/load_test.go, internal/httpapi/public_routes_test.go Locked transport and private-storage restrictions; positive resource budgets documented
Networks client/components/NetworkForm.vue, client/js/helpers/contextMenu.ts, internal/ircbridge/ Exact SASL labels, certificate enrollment prerequisite, Connect/Disconnect and diagnostics
Conversations client/components/MessageSearchForm.vue, Message.vue, client/js/helpers/messageThreads.ts, internal/session/activity_events.go Structured storage, search navigation, thread and Activity prerequisites
Navigation client/components/Windows/Settings.vue, client/js/keybinds.ts, test/client/js/responsivePanelsTest.ts Right-side mobile Settings drawer and gesture reference
Notifications client/components/Settings/Notifications.vue, internal/session/notifications.go, internal/webpush/, test/client/components/NotificationSettingsTest.ts Permission and OS checks; distinguish in-window, browser and push delivery
Account security client/components/Settings/Authenticator.vue, SecurityKeys.vue, internal/session/mfa_events.go, internal/auth/manager.go Exact enrollment labels, one-time codes, reset retains factors
Themes client/components/Settings/Themes.vue, internal/packages/ Existing theme workflows retained; package upgrade scope clarified
Uploads and sharing internal/messageshare/, internal/uploads/cleaner.go, client/components/Message.vue, test/client/js/messageShareTest.ts Copy message link, public snapshot warning, expiration and external Catbox boundary
Encryption internal/encryption/, internal/incommands/encrypt.go, related tests Server decrypts before storage/preview/search; not E2EE against Relay; commands retained
IRCv3 internal/ircbridge/, internal/irchandlers/, channel-rename/history tests Negotiated capabilities differ from advertised ISUPPORT/policy; remove stale live-network assertion, add bcrypt prerequisite, preserve anchors
Known limitations Reply/self-echo handlers and upstream bouncer source Qualify bouncer behavior by version/configuration; local IDs do not become server IDs
Security reporting Relay SECURITY.md Private reporting guidance retained

The new configuration reference covers all public internal/config/types.go fields and embedded defaults, including file-only settings, optional base URLs/theme color, and the intentionally non-configurable desktop marker. CLI coverage comes from every handler under cmd/relay/. Proxy and backup examples were checked against official Nginx, SQLite, PostgreSQL and Docker Compose documentation.

Application findings

  • Verified share-cache defect: after creating, reading and deleting a synthetic share, the server returned 404 while a browser controlled by Relay's service worker returned the cached page with 200. client/service-worker.js does not exclude share/message/ and falls back to cached content after HTTP errors. The guide now distinguishes server deletion from cached copies; no application fix was made.
  • Container legacy-home detection still tests config.js, while standalone fallback tests config.yaml. Specify RELAY_HOME and migrate explicitly; no application code was changed.
  • Restart Server calls os.Exit(0) after 300 ms. It relies on a supervisor and bypasses the normal signal-driven graceful shutdown path. Use normal service stop for consistent backups.
  • CLI password reset clears sessions but preserves factors; no dedicated CLI MFA reset exists. Disabling required MFA does not remove enrolled TOTP.
  • Administrator persistence serializes the full set of editable settings, so unrelated YAML changes can be masked by existing overrides. CLI precedence is reapplied on restart.

Verification results

Executed on 2026-09-06/07 UTC using Node 24.18.0, Go 1.26.7, Chromium 151, MkDocs 1.6.1 and Material 9.7.6. All server homes and build changes were under /tmp/relay-docs-audit; web listeners used 127.0.0.1. Only synthetic accounts were created, with no saved external IRC networks. No production data or credentials were used.

Executed locally

Check Result
npm ci, npm run build:client, Go build Passed in a git archive b67fdde3 source copy; used -buildvcs=false for the archive. Client build reported a loading-error script bundling notice and large-chunk warnings but completed
npm run watch; go run … start --dev Initial watch build completed; Go development server reached its loopback listener with a separate temporary home
CLI help and lifecycle Root/users/storage/migration/install help checked; pre-initialization add rejected; synthetic admin creation, explicit logging flag, list, password reset, schema migration, disabled-retention cleanup rejection, empty package listing and removal passed
First-account web setup Created administrator with logged token; returned to normal sign-in; first login succeeded
MFA enrollment and recovery Fresh sign-in, TOTP setup key, six-digit verification, eight recovery codes, next-password-login challenge and recovery-code login passed; consumed code reduced stored recovery hashes to seven
Administrator policy Required-MFA checkbox enabled and disabled through UI; values checked in admin-overrides.json; enabled policy survived restored startup
Remembered sessions MFA-authenticated browser state reconnected to the restored instance and retained access to Administration
Personal settings WebSocket setting change/readback passed
Shares and upload Synthetic snapshot creation/read and deletion passed at the server; a small multipart text upload returned 200. Browser share-cache defect recorded above
Backup/restore Gracefully stopped server, archived whole synthetic home, extracted to a different home, restarted on loopback; restored account SQLite PRAGMA integrity_check returned ok
Mobile Settings At 375 px the current-section trigger opened the drawer from the right; inspected screenshot and exact labels
Documentation Strict MkDocs build, generated-site validator, 32-page internal target/anchor check and git diff --check passed

Go checks passed for cmd/relay, internal/config, internal/auth, internal/session, internal/httpapi, internal/incommands, internal/messageshare, internal/uploads and internal/store/.... PostgreSQL tests needing RELAY_TEST_POSTGRES_DSN were skipped because no database was configured; the package's pass result is not a live PostgreSQL test.

The nine selected client test files passed 72 tests: TwoFactorAuthTest, AdminSettingsTest, SettingsTest, NotificationSettingsTest, keybindsTest, commandCatalogTest, activityTest, messageShareTest and messageSearchNavigationTest. These establish focused behavior, not an end-to-end IRC integration run. Full application lint/test suites were not run for this documentation-only change.

Callout verification

The reusable scripts/check-callouts.mjs checks eight ordinary/expandable warning, caution, danger and success examples below. Both relay-light and relay-dark were explicitly selected at 1440 px and 375 px, with screenshot inspection and collapse/expand checks. Body text uses the theme foreground on the surface; titles use the raised surface with distinct orange/red/green semantic accents.

Scheme Minimum body/title text contrast Minimum icon/border contrast Widths
relay-light 4.72:1 4.72:1 1440, 375 px
relay-dark 6.31:1 6.31:1 1440, 375 px

All exceed the required 4.5:1 text and 3:1 meaningful icon/border thresholds. Measured colors and ratios are retained as evidence. The README explains how to repeat the browser check; it writes new screenshots and measurements into a temporary artifact directory.

Source-reviewed or not exercised

SMTP delivery, OIDC identity-provider flows, physical security keys/passkeys, OS/browser push delivery, mobile PWA installation, desktop packages/Catbox, Jitsi, KLIPY, real IRC/SASL/WEBIRC, bouncer interoperability, remote package upgrades, DCC transfers, live PostgreSQL import/dump/restore, container upgrades/rollback and a deployed Nginx certificate/proxy were not exercised. Their procedures use source/tests and official external documentation. No live IRC history was created for the restore drill; search, threads, Activity, retention and protocol behavior rely on the cited implementation and focused tests.

The stopped synthetic restore checks account/configuration/SQLite readability, not disaster recovery for a production-sized dataset. Filesystem MFA recovery was source-reviewed; the ordinary CLI password-reset path was exercised. Preserve these distinctions when refreshing the audit.

Callout inspection fixture

These examples exercise the documentation theme in ordinary and expandable forms.

Warning

Read the operation and preserve a recoverable backup before proceeding.

Caution

Confirm the selected data directory before changing configuration.

Danger

Retention can permanently remove stored messages.

Success

A restore check confirms that the selected data can be read.

Expandable warning

Preserve the original files before applying a migration.

Expandable caution

Check both the title and body with each theme explicitly selected.

Expandable danger

Confirm the destination before restoring a database.

Expandable success

Record the tested version and representative restored messages.