feat(cli)!: expire tokens by default (#21783)

## Summary

> NOTE: Calling this out as a breaking change in case existing consumers
of the CLI depend on being able to see expired tokens OR being able to
delete tokens immediately.

Updates the `coder tokens rm` command to immediately expire a token by
ID, preserving the token record for audit trail purposes. Tokens can
still be deleted by passing `--delete`.

## Problem

During an incident on dev.coder.com, operators needed to urgently expire
an API key that was stuck in a hot loop. The only way to do this was via
direct database access:

```sql
UPDATE api_keys SET expires_at = NOW() WHERE id = '...';
```

This is not ideal for operators who may not have direct DB access or
want to avoid manual SQL.

## Solution

This PR adds:

- **API endpoint**: `PUT /api/v2/users/{user}/keys/{keyid}/expire` -
Sets the token's `expires_at` to now
- **SDK method**: `ExpireAPIKey(ctx, userID, keyID)` 
- **Updates CLI**: `coder tokens rm <name|id|token>` now _expires_ by
default. You can still delete by passing the `--delete` flag. The `coder
tokens list` command now also hides expired tokens by default. You can
`--include-expired` if needed to include them.
- **Audit logging**: The expire action is logged with old and new key
states

## Test plan

- Tests cover: owner expiring own token, admin expiring other user's
token, non-admin cannot expire other's token, 404 for non-existent token

Closes #21782

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Cian Johnston
2026-02-17 13:16:46 +00:00
committed by GitHub
co-authored by Claude Opus 4.5
parent a5f3acac2f
commit 4a3304fc38
19 changed files with 645 additions and 58 deletions
+18
View File
@@ -96,6 +96,24 @@ You can use the
server flag to set the maximum duration for long-lived tokens in your
deployment.
### Remove or expire a token
You can remove a token using the CLI or the API. By default, `coder tokens remove`
expires the token, (soft-delete):
```console
coder tokens remove <name|id>
```
Expired tokens can no longer be used for authentication but remain visible in
token listings.
To hard-delete a token, use the `--delete` flag:
```console
coder tokens remove --delete <name|id>
```
## API Key Scopes
API key scopes allow you to limit the permissions of a token to specific operations. By default, tokens are created with the `all` scope, granting full access to all actions the user can perform. For improved security, you can create tokens with limited scopes that restrict access to only the operations needed.