Skip to content

feat: Discord /run and /versions for the session-ops jobs - #81

Merged
Bilb merged 1 commit into
mainfrom
feat/discord-commands
Nov 3, 2026
Merged

Bilb merged 1 commit into
mainfrom
feat/discord-commands

Conversation

@Bilb

@Bilb Bilb commented Nov 3, 2026

Copy link
Copy Markdown
Collaborator

Two Discord slash commands: /run to start a job now, and /versions for each store's Session version against GitHub's. release-stats is removed. #71 builds /mau on top of this.

Commands

  • /run job:<job> starts session-ops@<job>.service by writing /run/session-ops/requests/<job>, which the job's path unit watches with PathChanged=, then waits up to 1.5 s for the unit's start time to change. Offered for the discord = true jobs: crowdin-sync and crowdin-duplicates for now. Refused while that job or a queued one is running or waiting, or when the queue's next run is sooner than the job's timeout. The check and the start share one lock; a command arriving while another holds it is refused at once rather than waiting past Discord's 3 s. The queue timer loses its random delay, so its next run is the scheduled time.
  • /versions replies in the channel with one line per store-versions platform from its state.json, which store-versions now writes 0644 for the relay. Read-only, so it is visible to everyone and skips the user and role allowlist.

What the app sees: HTTP interactions only, applications.commands scope, no gateway. /run is registered hidden from everyone but server administrators until Server Settings → Integrations grants it to a role.

Gates

  • Ed25519 signature within a 5-minute window, 60 s of forward skew.
  • DISCORD_GUILD_ID (DMs refused), and the channel in ALLOWED_CHANNEL_IDS when that is set.
  • ALLOWED_USER_IDS / ALLOWED_ROLE_IDS; both empty refuses everybody. /versions skips this check.
  • The relay runs as opsbot, which cannot start a unit. It can write only /run/session-ops/requests (root:opsbot 0770), where each discord = true job has a PathChanged= watch and nothing else. No polkit.

Registry and install

  • jobs.toml: discord; timeout is now checked as a systemd time span, since /run compares it with the queue's next run.
  • session-ops list --ready covers jobs a timer, the queue or a path unit starts; --timers lists those with a timer of their own, which is all install.sh enables timers for. --path-units lists the discord = true jobs.
  • install.sh: the opsbot account, the requests directory, the path units of the ready discord = true jobs, and session-ops-discord.service once discord.env has content.
  • release-stats (on-demand download counts) and its doc are removed.

Deploy

/etc/session-ops/discord.env, then the location = /discord/interactions block from nginx-webhooks.conf copied into the live file by hand, since certbot owns it, then session-ops discord-register once. Steps in deploy/README.md under "Discord commands".

Not yet done: the Discord side ran end to end against a test app (verification, registration, the gates, /run replies). Nothing has run on the host. After deploying:

  • An unsigned POST gets 401.
  • systemctl list-units 'session-ops@*.path' lists crowdin-duplicates and crowdin-sync, active.
  • /run crowdin-duplicates starts the job and its post appears.
  • /versions lists the seven platforms.

Tests

uv run --locked python -m unittest discover -s tests -t . (906 OK, 1 skipped), ruff check . clean.

/run starts a `discord = true` job through its path unit; /versions shows each
platform's store and GitHub versions from store-versions' state. The relay runs as
opsbot, which can only write request files the path units watch.

release-stats is removed.
@Bilb
Bilb merged commit 9b10da2 into main Nov 3, 2026
3 checks passed
@Bilb
Bilb deleted the feat/discord-commands branch November 3, 2026 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant