Skip to content

feat(cli): default backoffice invites to a week, configurable - #279

Merged
scarmuega merged 2 commits into
mainfrom
feat/cli-invite-ttl-config
Aug 11, 2026
Merged

feat(cli): default backoffice invites to a week, configurable#279
scarmuega merged 2 commits into
mainfrom
feat/cli-invite-ttl-config

Conversation

@scarmuega

@scarmuega scarmuega commented Aug 11, 2026

Copy link
Copy Markdown
Member

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 an invite_ttl_min key — operators populate that section by copying it out of the RPC's rpc.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 * 60 so it reads as a duration rather than a magic number. Precedence: --ttl-min[email].invite_ttl_min → one week.

[email]
invite_ttl_min = 10080   # optional; omit for the same thing

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_invite checks against the Auth0 profile, so the exposure is a stolen-mailbox scenario — in which the attacker has the account anyway. --ttl-min narrows it for a sensitive invite.

Testing

cargo test --lib — 161 passed, unchanged. This is config plumbing over the paths #278 already covers: the TTL reaches apply_user_invite as the same Duration, and the existing dry-run test still pins that nothing is sent. Verified --help renders 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

scarmuega and others added 2 commits August 11, 2026 11:51
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>
@scarmuega scarmuega changed the title feat(cli): let the config set a default invite ttl feat(cli): default backoffice invites to a week, configurable Aug 11, 2026
@scarmuega
scarmuega merged commit ed4812c into main Aug 11, 2026
7 of 8 checks passed
@scarmuega
scarmuega deleted the feat/cli-invite-ttl-config branch August 11, 2026 15:01
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