Validate PlatformInstance on creation — check it is actually a Lemmy instance #132

Open
opened 2026-08-10 22:59:19 +02:00 by myrmidex · 0 comments
Owner

Summary

Adding a PlatformInstance has zero validation beyond the database constraints. You can enter https://google.com as a Lemmy instance URL and it is accepted without complaint. The failure surfaces much later — when channel creation tries to list communities or publishing tries to post — as an opaque connection error with no indication that the instance URL itself is wrong.

Current state

  • PlatformInstance model has url, name, platform (enum), is_active — no validation beyond required|url
  • Channel creation (Channels.php:createChannel()) calls CommunityDirectory::forInstance($instance) which constructs a LemmyApiService with the raw URL and hits GET /api/v3/community/list
  • If the URL points to a non-Lemmy server, the HTTP call fails or returns garbage, and the error is surfaced as "Could not reach this instance to list its communities"
  • No validation at PlatformInstance creation time at all

Design

Approach: NodeInfo check at create time

Forgejo/Lemmy instances expose a NodeInfo endpoint at /.well-known/nodeinfo/nodeinfo/2.0 (or 2.1). The response includes software.name (e.g., lemmy, forgejo) and software.version. Checking this at instance creation time catches:

  • Non-Lemmy URLs (wrong software name)
  • Dead URLs (connection refused / timeout)
  • URLs that return HTML instead of JSON (a redirect to a login page, a CDN 404 page, etc.)

What to validate

  1. Reachability — the URL resolves and responds. If not, surface a field error: "Could not reach this server."
  2. NodeInfo presence/.well-known/nodeinfo returns JSON with a link to a nodeinfo document. If not, surface: "This server does not appear to be a Lemmy instance."
  3. Software identity — the linked nodeinfo document's software.name contains lemmy. If not, surface: "This server appears to be running {name}, not Lemmy."

Where to validate

In Channels.php / CreateChannelAction, when newPlatformInstanceId references a newly-created instance. Or better: in the PlatformInstance creation path itself (onboarding flow + any future admin CRUD). The onboarding flow in Onboarding.php already creates instances — add validation there.

Graceful degradation

If the NodeInfo endpoint is unreachable (temporary network issue, instance is down), the validation should:

  • Fail with a distinct error ("Could not verify this instance — it may be temporarily down")
  • NOT block creation permanently — offer a "skip verification" option or allow retry

This prevents a transient Lemmy outage from blocking instance setup entirely.

Tasks

  • Add NodeInfoService (or extend LemmyApiService) to resolve /.well-known/nodeinfo → nodeinfo document → software.name
  • Validate at PlatformInstance creation in the onboarding flow (Onboarding.php)
  • Validate at PlatformInstance creation in any other entry point (channels page, admin panel if applicable)
  • Distinct error messages for: unreachable, not Lemmy, NodeInfo missing
  • "Skip verification" escape hatch for transient failures
  • Tests: valid Lemmy instance accepted, non-Lemmy rejected, dead URL rejected, NodeInfo missing rejected, skip-verification path
  • API calls mocked in tests (network-offline rule)

Edge cases

  • Instance behind a reverse proxy that doesn't forward /.well-known/nodeinfo — should be skippable
  • Self-signed certificates on dev instances — HttpFetcher should not reject these (already handled? confirm)
  • Lemmy forks that report a different software.name — the check should be a warning, not a hard block (or: pattern-match on known Lemmy names)
  • IPv6-only instances — should Just Work if the server has IPv6 connectivity

Acceptance criteria

  • Creating a PlatformInstance with a non-Lemmy URL is rejected with a clear field error
  • Creating with a dead URL is rejected with a distinct error
  • Creating with a valid Lemmy instance succeeds
  • A "skip verification" path exists for transient failures
  • Existing tests for instance creation still pass
  • Network calls are mocked in tests
  • #114 — validate community name exists; same class of problem (late failure at channel creation instead of early validation at instance creation)
  • #126 — community typeahead; depends on the instance being valid to list communities
## Summary Adding a `PlatformInstance` has zero validation beyond the database constraints. You can enter `https://google.com` as a Lemmy instance URL and it is accepted without complaint. The failure surfaces much later — when channel creation tries to list communities or publishing tries to post — as an opaque connection error with no indication that the instance URL itself is wrong. ## Current state - `PlatformInstance` model has `url`, `name`, `platform` (enum), `is_active` — no validation beyond `required|url` - Channel creation (`Channels.php:createChannel()`) calls `CommunityDirectory::forInstance($instance)` which constructs a `LemmyApiService` with the raw URL and hits `GET /api/v3/community/list` - If the URL points to a non-Lemmy server, the HTTP call fails or returns garbage, and the error is surfaced as "Could not reach this instance to list its communities" - No validation at `PlatformInstance` creation time at all ## Design ### Approach: NodeInfo check at create time Forgejo/Lemmy instances expose a NodeInfo endpoint at `/.well-known/nodeinfo` → `/nodeinfo/2.0` (or 2.1). The response includes `software.name` (e.g., `lemmy`, `forgejo`) and `software.version`. Checking this at instance creation time catches: - Non-Lemmy URLs (wrong software name) - Dead URLs (connection refused / timeout) - URLs that return HTML instead of JSON (a redirect to a login page, a CDN 404 page, etc.) ### What to validate 1. **Reachability** — the URL resolves and responds. If not, surface a field error: "Could not reach this server." 2. **NodeInfo presence** — `/.well-known/nodeinfo` returns JSON with a link to a nodeinfo document. If not, surface: "This server does not appear to be a Lemmy instance." 3. **Software identity** — the linked nodeinfo document's `software.name` contains `lemmy`. If not, surface: "This server appears to be running {name}, not Lemmy." ### Where to validate In `Channels.php` / `CreateChannelAction`, when `newPlatformInstanceId` references a newly-created instance. Or better: in the `PlatformInstance` creation path itself (onboarding flow + any future admin CRUD). The onboarding flow in `Onboarding.php` already creates instances — add validation there. ### Graceful degradation If the NodeInfo endpoint is unreachable (temporary network issue, instance is down), the validation should: - Fail with a distinct error ("Could not verify this instance — it may be temporarily down") - NOT block creation permanently — offer a "skip verification" option or allow retry This prevents a transient Lemmy outage from blocking instance setup entirely. ## Tasks - [ ] Add `NodeInfoService` (or extend `LemmyApiService`) to resolve `/.well-known/nodeinfo` → nodeinfo document → `software.name` - [ ] Validate at `PlatformInstance` creation in the onboarding flow (`Onboarding.php`) - [ ] Validate at `PlatformInstance` creation in any other entry point (channels page, admin panel if applicable) - [ ] Distinct error messages for: unreachable, not Lemmy, NodeInfo missing - [ ] "Skip verification" escape hatch for transient failures - [ ] Tests: valid Lemmy instance accepted, non-Lemmy rejected, dead URL rejected, NodeInfo missing rejected, skip-verification path - [ ] API calls mocked in tests (network-offline rule) ## Edge cases - **Instance behind a reverse proxy** that doesn't forward `/.well-known/nodeinfo` — should be skippable - **Self-signed certificates** on dev instances — `HttpFetcher` should not reject these (already handled? confirm) - **Lemmy forks** that report a different `software.name` — the check should be a warning, not a hard block (or: pattern-match on known Lemmy names) - **IPv6-only instances** — should Just Work if the server has IPv6 connectivity ## Acceptance criteria - [ ] Creating a `PlatformInstance` with a non-Lemmy URL is rejected with a clear field error - [ ] Creating with a dead URL is rejected with a distinct error - [ ] Creating with a valid Lemmy instance succeeds - [ ] A "skip verification" path exists for transient failures - [ ] Existing tests for instance creation still pass - [ ] Network calls are mocked in tests ## Related - #114 — validate community name exists; same class of problem (late failure at channel creation instead of early validation at instance creation) - #126 — community typeahead; depends on the instance being valid to list communities
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lvl0/fedi-feed-router#132
No description provided.