No description
  • JavaScript 99.3%
  • Dockerfile 0.7%
Find a file
bray ba6d4ceac7
All checks were successful
CI / test (push) Successful in 9s
CI / publish (push) Successful in 38s
Update .forgejo/workflows/ci.yml
2026-09-12 19:11:04 +02:00
.forgejo/workflows Update .forgejo/workflows/ci.yml 2026-09-12 19:11:04 +02:00
docs feat: add invite-only system enrollment 2026-09-12 11:23:42 -04:00
src feat: add rich system-aware front notifications 2026-09-12 12:55:52 -04:00
test feat: add destination routing admin page 2026-09-12 11:32:37 -04:00
.dockerignore feat: add multi-system Dispatch validation receiver 2026-09-12 11:14:26 -04:00
.env.example feat: extend setup invitations to 24 hours 2026-09-12 11:27:35 -04:00
.gitignore feat: add multi-system Dispatch validation receiver 2026-09-12 11:14:26 -04:00
Dockerfile feat: add invite-only system enrollment 2026-09-12 11:23:42 -04:00
package.json feat: add multi-system Dispatch validation receiver 2026-09-12 11:14:26 -04:00
README.md feat: add destination routing admin page 2026-09-12 11:32:37 -04:00

Automatic Front Notifications

Private, self-hosted front-change notifications for authorized PluralKit systems.

Current milestone

This repository currently contains only the Dispatch validation receiver. It proves whether front changes initiated in Constellations synchronise into PluralKit and produce usable Dispatch events. It does not call the PluralKit API, post to Discord, retain member data, or calculate front changes.

The receiver accepts POST /webhooks/pluralkit, validates the Dispatch signing_token in constant time, restricts events to configured systems, and writes only this data for switch events: receipt time, event type, system ID, and switch ID. GET /healthz has no configuration or member data.

PluralKit requires invalid signed PING requests to receive HTTP 401; accepting them can cause its webhook to be removed. A valid PING receives HTTP 200 and creates no record. See the PluralKit Dispatch documentation.

Run locally

cp .env.example .env
set -a; . ./.env; set +a
node src/server.js

The deployment must mount /data as the service's only writable location and terminate public HTTPS at the existing reverse proxy. Do not expose a port directly to the internet or add the infrastructure reference before the validation plan is approved.

The approved validation placement is Runner behind the Primary reverse proxy at https://front.delaire.xyz. The shared Discord destination will be configured only on the server; friends do not supply webhooks. The encrypted SQLite database is the live multi-system registry. See the deployment runbook.

Invite only setup

An administrator creates a one-use invitation that expires after 24 hours by default. The friend opens its /setup/... URL, copies the displayed pk;s webhook ... command, and confirms it in PluralKit. The page polls a capability-limited status endpoint and confirms the first signed PING automatically binds the system and its Dispatch token. The token is encrypted before it reaches SQLite; neither the friend nor the administrator copies it into an environment file.

Use /admin to add a destination, optionally include a Discord thread ID, select one or more destinations for a setup invitation, and review connected systems. The admin page requires ADMIN_TOKEN; it never returns stored webhook URLs.

Validation procedure

  1. Obtain the friend's explicit consent for the receiver, destination, and retained validation fields.
  2. Choose a dedicated hostname and configure the reverse proxy for HTTPS to this receiver.
  3. Register https://HOSTNAME/webhooks/pluralkit from the friend's PluralKit account. Store the generated signing token only in the deployment secret store.
  4. Confirm the valid PING receives 200 and an intentionally invalid PING receives 401.
  5. Change the front in Constellations, including a co-front join. Compare the recorded switch event type, ID, and receipt time with the change time.
  6. Repeat through PluralKit directly, then edit and delete a current switch to observe correction events.
  7. Keep no raw payloads. Delete the validation journal when the test concludes, unless the friend agrees to retain it for a defined operational period.

Next milestone

Only after the validation confirms usable Constellations-originated Dispatch events: implement the debounced current-fronter refresh, SQLite deduplication, Discord webhook formatting, retries, and the complete state-transition test suite.