Skip to content

Add POST /invite-codes/disable, authenticated by Cloudflare Access - #17

Merged
northernpolaris merged 1 commit into
mainfrom
feat-machine-facing-disable
Sep 9, 2026
Merged

northernpolaris merged 1 commit into
mainfrom
feat-machine-facing-disable

Conversation

@aendra-rininsland

Copy link
Copy Markdown
Contributor

Prerequisite for NorthskySocial/invite-vetting#38 — "blocking a user should invalidate their invite code if they have an unused one".

Why a new route

/disable-invite-codes already disables codes, but it authenticates with InviteCodeAdmin, which extracts from tower_sessions::Session plus an OTP check — a browser cookie. The vetting Worker holds a Cloudflare Access service token, which satisfies AccessClient only, so that endpoint is unreachable from it.

That is the same asymmetry /invite-codes/issue was added to solve:

Purpose Browser-facing Machine-facing
create /create-invite-codes /invite-codes/issue
disable /disable-invite-codes /invite-codes/disable (this PR)

The browser-facing route is untouched, so the admin UI is unaffected.

Behaviour

Same request body as the existing route (DisableInviteCodeSchema — codes and accounts), same call through to com.atproto.admin.disableInviteCodes.

Disabling is unconditional and idempotent. The issue says "if they have an unused one", but a redeemed code cannot be redeemed again, so disabling it is a no-op — and checking first would mean trusting a use-count read taken a moment before the write. Unconditional is both simpler and free of that race.

An empty request is a 400, not a 200. Disabling nothing and reporting success reads to the caller exactly like a code having been revoked, and that is the one outcome here that must not be indistinguishable from failure.

Checks

  • cargo build clean
  • cargo test — 57 passing, 5 new
  • cargo clippy --all-targets clean, cargo fmt --check clean

The new tests mirror issue_invite_code's: no assertion, forged assertion, and Access unconfigured all give 401, and the PDS is never reached before authenticating (pds_endpoint points at a closed port, so a 401 also proves no outbound call was attempted).

Deploy ordering

This must ship before the vetting-tool side, which I am writing next. Nothing depends on it until then, so it is safe to merge on its own.

🤖 Generated with Claude Code

The vetting tool needs to disable an invite code when it blocks the applicant
that code was issued to. A code already sitting in someone's inbox outlives
the decision to bar them, so blocking without revoking leaves a working way
in (NorthskySocial/invite-vetting#38).

/disable-invite-codes already does this, but authenticates with the browser
session cookie and an OTP check. A service holding a Cloudflare Access token
cannot satisfy that extractor, so the endpoint is unreachable from another
Worker.

This mirrors /invite-codes/issue, which exists as the machine-facing
counterpart to /create-invite-codes for exactly the same reason. The
browser-facing route is left alone.

Disabling is unconditional and idempotent. A redeemed code cannot be redeemed
again, so disabling it is a no-op rather than something to check for first —
and checking would mean trusting a use-count read taken a moment before the
write.

An empty request is rejected rather than reported as success: disabling
nothing and returning 200 reads to the caller exactly like a code having been
revoked, which is the one outcome that must not be indistinguishable from
failure here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@northernpolaris
northernpolaris merged commit 02cd01b into main Sep 9, 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