keryx auth refresh¶
Description¶
Keep unattended posting alive: refresh/rotate each platform's tokens where it can,
and alert where it can't (spec 0010-auth-refresh.md).
Run it on a schedule in the owning project, well inside each token's window — a
silently stale token is the top unattended failure mode.
Per platform, by token shape:
| Platform | Action |
|---|---|
| refresh-in-place near expiry (new ~60-day token) | |
| YouTube | health-check the durable refresh token |
| TikTok | rotate the refresh token + persist the new one |
| can't refresh (standard app) → alert: re-auth by DATE |
It is side-effecting (writes tokens) and so is gated off the MCP surface.
Usage¶
keryx auth refresh/keryx auth refresh all— every enabled platform (the CI entrypoint).keryx auth refresh tiktok— one platform.--dry-run— report each platform's token status + the action it would take; change nothing.
Exits non-zero if any platform needs attention (so a scheduled pipeline goes red), and fires the configured alert backend.
Configuration¶
Both backends are config-selected (auth.*), like keryx's generation providers
— pick the one that suits your infra; adding another is purely additive.
auth:
writeback:
backend: local # local (keychain/config) | gitlab (CI variable API)
# gitlab:
# project: "phpboyscout/blog" # or CI_PROJECT_ID in a pipeline
# api_url: "https://gitlab.com/api/v4" # or CI_API_V4_URL
alerts:
backend: none # none (red pipeline only) | webhook | email
# webhook:
# url: "" # or ALERT_WEBHOOK_URL
# email:
# host: smtp.example.com
# port: 587
# from: keryx@phpboyscout.uk
# to: ["matt@phpboyscout.uk"]
Write-back — where refreshed tokens land¶
local(default) — the OS keychain, else the config file. For CLI use.gitlab— updates the project's CI/CD variable (the same masked, protected variable the publisher reads, e.g.TIKTOK_REFRESH_TOKEN) via the GitLab API, so the next scheduled run sees the rotated token. This is what makes the unattended path work — an ephemeral CI job otherwise can't write back the variables it read. NeedsGITLAB_TOKEN(a project/group access token,apiscope —CI_JOB_TOKENcan't write variables).project/api_urldefault to the predefinedCI_PROJECT_ID/CI_API_V4_URLin a pipeline. The variable must already exist (masked + protected) — the backend updates its value, it never creates a new, unmasked secret.
Alerts — where a "needs attention" goes¶
A non-zero exit (red pipeline) is always on; the notifier adds an out-of-band ping.
none(default) — rely on the red pipeline only.webhook— POST to a Slack/Teams/Discord incoming webhook (auth.alerts.webhook.urlorALERT_WEBHOOK_URL).email— send over SMTP. Host/port/from/to from config; credentials fromALERT_SMTP_USERNAME/ALERT_SMTP_PASSWORD. Port defaults to 587.
Secrets are resolved as for posting (env → keychain → config); the same client
ids/secrets the adapters use (TIKTOK_CLIENT_SECRET, YOUTUBE_CLIENT_SECRET,
INSTAGRAM_APP_SECRET, LINKEDIN_CLIENT_SECRET) are needed to refresh.
Flags¶
| Flag | Description | Default | Required |
|---|---|---|---|
--dry-run |
validate only, report token status without changing anything | false |
Scheduling¶
keryx is stateless — the schedule lives in the owning project's CI (a weekly
scheduled pipeline running keryx auth refresh all with auth.writeback.backend
set for that environment). See spec 0010 §8.