Peering: admin can enable/disable it from the running instance #134
Labels
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Cordy/Cairn#134
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Decided with Nikola (2026-08-07). Today peering needs
peering.statePathset inconfig.jsonbefore the admin panel does anything — a deploy-time prerequisite with no in-app way to turn the feature on. That is why "generate key" 404s on the dogfood.The design
An admin turns peering on and off from the running instance, entirely in the UI.
Default
peering.statePathto/data/.cairn/peering.json, so the peering subsystem is always mounted and the admin panel always functions. The state file is created lazily and is empty until keys/peers are added — no behavioural change beyond the panel working.An enable/disable switch at the top of the Peering panel, bound to the existing runtime
peeringEnabledsetting. Off by default. When off: the panel still lets an admin configure peers (issue keys, register), so they can set everything up before going live, but no transfers flow and the end-user send surface is hidden. Flipping it on makes peering live immediately — no restart.Gate the end-user send surface on
peeringEnabled. Thefeat.peerSendprobe (GET /api/v1/peering/peers) and the send/transfers endpoints return unavailable when peering is off, so "Send to peer" and the Transfers nav only appear once an admin has turned peering on. Sending from an instance with peering off is refused for the same reason receiving is.Why this shape
statePathis filesystem plumbing; it should not double as the feature's on/off switch.peeringEnabled(already in the settings store, already the transport's runtime gate) becomes the single, admin-controlled master switch, surfaced where an admin looks to configure peering. Separates "where state lives" (config) from "is the feature on" (runtime, self-service).Supersedes the "graceful not-enabled" notice added in #131/v0.4.5 for the normal case — with statePath defaulted, the admin API is always mounted, so that 404 notice only remains as defence for an operator who deliberately sets
statePath: "".Follow-up already noted: #129 (warn on group-only receivers lists without an IdP admin client).
Shipped in v0.4.6 (PR #135), live on the dogfood.
The problem this closes. Peering had two independent gates that had drifted apart.
peering.statePath(deploy-time config) decided whether the subsystem was mounted at all — the admin panel, key issuance, peer registration.peeringEnabled(runtime setting) was meant to decide whether the transport answered. On the dogfood, statePath was unset, so the whole subsystem was absent: the admin panel'sPOST /api/v1/admin/peering/keys404'd (root cause of the "generate key does nothing" / "Not Found" reports in #131), and there was no way to turn peering on from the running instance — it required a redeploy.Resolution — mount always, answer on demand.
peering.statePathnow defaults to/data/.cairn/peering.json. The subsystem is mounted on every instance, so the admin panel, key issuance and peer registration always work.peering.Openstill creates no file until the first key/peer is registered, so an instance that never uses peering carries no state.PeeringSendAPIgainsEnabled func() bool.send/peers/transfersreturn503when it reports false (nil= ungated, so existing tests are untouched). Because the send UI feature-probesGET /api/v1/peering/peers, the 503 makes the user-facing send surface auto-hide until an admin turns peering on — no extra frontend gate needed. New testTestSendSurfaceUnavailableWhenPeeringOffasserts all three endpoints 503 when disabled.peerOnclosure (settingsStore.Get().PeeringEnabled) intoPeeringSendAPI.Enabled. The gRPC control plane and blob route already gate onpeerOn, so an external peer hitting a disabled instance also gets 503.serverSettings.peeringEnabled. Toggling re-PUTs the full settings object with the flag flipped through the existingPUT /api/v1/settings(admin-gated) — no new endpoint. A quiet notice explains what "off" means; i18n for en/de/fr/it.Net UX. An admin opens Instance peering on any instance, sees the switch, and turns peering on or off live. Off → transport 503s, send UI hidden for everyone, but keys and peers can still be prepared. On → everything answers. No redeploy, no config edit, no secret edit.
Verified: gofmt/vet clean, full
go test ./...green (incl. the new test),go build ./...clean, both JS blocks passnode --checkon the branch; imagecordy/cairn:v0.4.6(sha256:e837d5d9…) built byrelease.ymland confirmed Running 1/1 ascairn-encon the dogfood.