feat(cli): default backoffice invites to a week, configurable - #279
Merged
Conversation
invite-user took its lifetime only from --ttl-min, defaulting to 15 minutes. Operators who want a standing window had to remember the flag on every invite, and forgetting it silently fell back to 15 — short enough that an invite can expire before the invitee reads the mail. `[email].invite_ttl_min` now supplies the default, matching the key the RPC already reads from its own config. Precedence is --ttl-min, then the config, then 15, so nothing changes for a config that omits it. Also refuses a zero ttl: it mails a code that has already expired, and the failure surfaces only when the invitee clicks it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The fallback matched the RPC's 15 minutes, which is the wrong default for this caller. A Console invite is sent by someone watching the screen who can resend on the spot; a backoffice invite goes out on an operator's schedule to someone who may not be expecting it, so the window has to survive a weekend. Config and --ttl-min still take precedence, so anyone wanting the short window can still ask for it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
invite-user(#278) took its lifetime only from--ttl-min, defaulting to 15 minutes. Two problems, and the second is the real one.The default was wrong for this caller. 15 minutes is inherited from the RPC, where it fits: a Console invite is sent by someone watching the screen, who notices an expiry and resends on the spot. A backoffice invite goes out on an operator's schedule to someone who may not be expecting it — nobody is watching, and the first sign of trouble is the invitee clicking a dead link days later. The window has to survive a weekend.
There was no way to set a standing policy. An operator wanting week-long invites had to remember the flag every time, and forgetting it fell back to 15 minutes silently. Worse, the
[email]section of the CLI config already carries aninvite_ttl_minkey — operators populate that section by copying it out of the RPC'srpc.toml, where the key is live — so the config looked like it controlled this and didn't.What
Default is now one week, written as
7 * 24 * 60so it reads as a duration rather than a magic number. Precedence:--ttl-min→[email].invite_ttl_min→ one week.The RPC keeps its 15 minutes — this constant is backoffice-only, and the divergence is deliberate and documented at the constant.
Also refuses
--ttl-min 0. That mails a code which has already expired, and the failure surfaces only when the invitee clicks it — worth catching before spending the send rather than after.Resolution lives in the backoffice driver rather than the binary, so the precedence rule sits next to the config that feeds it and the binary just forwards an
Option.Trade-off
A longer window means a valid code sits in a mailbox for longer. It is single-use and bound to one email address, which
accept_user_invitechecks against the Auth0 profile, so the exposure is a stolen-mailbox scenario — in which the attacker has the account anyway.--ttl-minnarrows it for a sensitive invite.Testing
cargo test --lib— 161 passed, unchanged. This is config plumbing over the paths #278 already covers: the TTL reachesapply_user_inviteas the sameDuration, and the existing dry-run test still pins that nothing is sent. Verified--helprenders the fallback and that omitting both flag and key yields a week.Not in this PR
The Console's 15 minutes has the same smell, and it is one line in
.github/iac/main.tf:59. Left alone: it changes invite behaviour for every customer and needs a deploy, so it deserves its own decision rather than riding along with a backoffice change.🤖 Generated with Claude Code