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.jsdoes not excludeshare/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 testsconfig.yaml. SpecifyRELAY_HOMEand migrate explicitly; no application code was changed. Restart Servercallsos.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.