Skip to content

feat: alert before a token the jobs use expires - #69

Merged
Bilb merged 3 commits into
mainfrom
feat/token-expiry
Oct 6, 2026
Merged

Bilb merged 3 commits into
mainfrom
feat/token-expiry

Conversation

@Bilb

@Bilb Bilb commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Adds token-expiry, a daily job (09:00 Melbourne, as sessionops) that posts to the alerts channel 14, 7 and 1 days before a token expires, and once when it has. Quiet otherwise; a new expiry or a rotated token starts its alerts over.

Token Expiry from
GITHUB_PRS_TOKEN GitHub's github-authentication-token-expiration response header
CLAUDE_CODE_OAUTH_TOKEN A year after the job first saw it, tracked by a 12-hex-char SHA-256 fingerprint in its state. A token installed before the job ran takes its real issue date from [issued] in expiry.toml, which applies only while that fingerprint matches.
CROWDIN_API_TOKEN /etc/session-ops/expiry.toml, by hand (no API exposes it); reported until it has a date or "never"

The Zendesk API token, Discord webhooks and the GitHub App key do not expire.

Trade-off: fingerprinting the Claude token means the unit loads zendesk.env, so the Zendesk secrets are in this unit's environment too, and the job is only ready on a host where zendesk.env has content.

Also: install.sh installs deploy/env/*.example, which now includes expiry.toml.example; a doc page at docs/jobs/token-expiry.md; the drop-in golden updated for the new job.

Deploying

install -m 644 /etc/session-ops/expiry.toml.example /etc/session-ops/expiry.toml
# set CROWDIN_API_TOKEN, and [issued.CLAUDE_CODE_OAUTH_TOKEN] with the fingerprint the dry run prints
git -C /opt/session-ops pull && /opt/session-ops/deploy/install.sh
systemd-run --pipe --wait -p User=sessionops \
  -p EnvironmentFile=/etc/session-ops/alerts.env -p EnvironmentFile=/etc/session-ops/github-prs.env \
  -p EnvironmentFile=/etc/session-ops/zendesk.env \
  /opt/session-ops/.venv/bin/session-ops-token-expiry --dry-run

Testing

  • uv run python -m unittest discover -s tests -t .: 759 tests pass; ruff check clean.
  • Local runs against the live GitHub API: the probe works, and a second run keeps the Claude token's first-seen date. The header format matches what angus's token returns (2027-10-02 03:00:00 UTC).

A daily token-expiry job posts to the alerts channel 14, 7 and 1 days before a
token expires, and once when it has. The GitHub token's expiry comes from
GitHub's response header; the Claude Code token is dated by fingerprint from the
day the job first sees it, with an optional issue date for one that predates the
job; the Crowdin token's is recorded in /etc/session-ops/expiry.toml.
Comment thread src/session_ops/monitor/token_expiry.py Outdated
Comment thread src/session_ops/monitor/token_expiry.py Outdated
Bilb added 2 commits October 6, 2026 13:50
The 09:00 Melbourne run is the previous day in UTC, so comparing dates could
call an expiry hours away "tomorrow", skip the alert on the expiry date, and
report expiry two days late. Expiries are now UTC times (a date-only one counts
from its start) and the alerts say "in less than 14 days / 7 days / 24h".
@Bilb
Bilb merged commit 8a91432 into main Oct 6, 2026
3 checks passed
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.

2 participants