Skip to content

CDX-12: console: support expirations on app passwords - #38444

Draft
jubrad wants to merge 2 commits into
MaterializeInc:mainfrom
jubrad:justin/cdx-12-console-support-expirations-on-app-passwords-and-show-expiry
Draft

CDX-12: console: support expirations on app passwords#38444
jubrad wants to merge 2 commits into
MaterializeInc:mainfrom
jubrad:justin/cdx-12-console-support-expirations-on-app-passwords-and-show-expiry

Conversation

@jubrad

@jubrad jubrad commented Aug 25, 2026

Copy link
Copy Markdown
Member

CDX-12

Problem

Console app passwords (Frontegg user/tenant API tokens) were immortal: the create flow only took a description, and the list gave no signal about which credentials were stale. That blocks customers with credential-rotation requirements and makes cleanup guesswork.

Solution

Frontegg already supports this end to end, so no backend work was needed. Confirmed against frontegg/openapi-public/identity.json:

  • POST .../{users,tenants}/api-tokens/v1 accept expiresInMinutes (omitted = never expires).
  • Both GET list responses return expires (date-time). Note the field is expires, not expiresAt.
  • There is no lastUsed/lastSeen field anywhere in the identity spec, so "show last use" is not buildable from Frontegg. Follow-up write-up is on the Linear issue.

Changes:

  • Thread an optional expiresInMinutes through createUserApiToken / createTenantApiToken and useCreateApiToken, and type expires on the token interfaces.
  • Add an Expiration select to the new app password modal: 30 / 60 / 90 days or "No expiration", defaulting to 90 days.
  • Add an Expires column to the list. "Never" when unset, otherwise the formatted date plus a red "Expired" or yellow "Expiring soon" (within 7 days) pill.

Testing

New src/access/AppPasswordsPage.test.tsx covers a legacy token with no expires rendering "Never", the expired and expiring-soon pills, the default create posting expiresInMinutes: 129600, and "No expiration" posting no expiresInMinutes. yarn lint, yarn typecheck, and the console suite pass locally; console-e2e-test / console-e2e-test-prod exercise the real-region path.

Reviewer notes

  • The inline creators (connectComponents, ConnectMcpPanel, MzCliAppPasswordPage) are deliberately unchanged. The param is optional, so those keep creating non-expiring passwords. Adding an expiration control there is a follow-up.
  • Expiry is set-at-creation only; existing passwords are unaffected and render as "Never".
  • src/frontegg-auth's active_sessions cache serves repeat authentications without calling Frontegg and refreshes at ~0.8x JWT lifetime, so an already-authenticated app password can keep working for up to one refresh period past its expiry. This is the same bounded window that already exists when a password is deleted, not a new regression.
  • src/frontegg-mock models no expiry (it accepts only description). Console e2e hits real staging Frontegg so the mock is not on this path; teaching it expiresInMinutes/expires is a cheap follow-up if a Rust integration test ever needs it.

🤖 Generated with Claude Code

jubrad added 2 commits August 24, 2026 22:52
Frontegg's user and tenant API token endpoints accept `expiresInMinutes`
on create and return `expires` on list, but the console never used
either, so every app password was immortal and the list gave no signal
about staleness.

Add an Expiration select to the new app password modal (30/60/90 days or
no expiration, defaulting to 90 days) and an Expires column to the list
that renders "Never" for passwords without an expiration and flags
expired and soon to expire ones with a status pill.

CDX-12
Drop the redundant aria-label on the expiration select so the
label/id wiring is what tests exercise, let StatusPill derive its own
text, and cover the service password path in the test.

CDX-12
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