guibranco / guibranco/logstream-ui
[FEATURE] Scoped read token management in Applications screen
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 0
- Avg merge
- 15m
- Merged PRs (30d)
- 49
Description
## Summary
Extend the Applications screen to support generating and rotating **scoped read tokens** per client, with a secure one-time display modal matching the existing API token reveal flow.
> **Depends on:** [`[FEATURE] Scoped read keys per registered client`](https://github.com/guibranco/logstream-server/issues) in `guibranco/logstream-server`
## Motivation
Once the server supports per-client read tokens, operators need a UI to generate them for individual teams without exposing the admin `UI_SECRET`.
## Proposed changes
### ClientTable β new action
Add a **"Generate read token"** button (key icon) in the Actions column alongside the existing Edit, Rotate API token, and Delete buttons.
### TokenRevealModal β reuse for read token
Reuse the existing `TokenRevealModal` component with adjusted copy:
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β π Scoped read token for billing-api β
β β
β This token grants read-only access to logs from β
β billing-api only. Store it now β it will not be β
β shown again. β
β β
β Token: [____________________________] [Copy] β β
β β
β Usage: β
β Authorization: Bearer β
β β Can only read logs where app_key = billing-api β
β β
β [ I've saved the token ] β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
### RotateConfirmModal β read token variant
```
Rotate read token for "billing-api"?
Anyone currently using the old read token will lose
access until they update their configuration.
[Cancel] [Rotate read token]
```
## Files to modify / create
- `src/components/clients/ClientTable.tsx` β add Generate read token action button
- `src/components/clients/TokenRevealModal.tsx` β accept a `tokenType` prop (`'api' | 'read'`) to adjust copy
- `src/components/clients/RotateConfirmModal.tsx` β accept `tokenType` prop
- `src/hooks/useClients.ts` β add `useRotateReadToken()` mutation calling `POST /api/clients/{key}/rotate-read-token`
## UX details
- The read token action is shown as a secondary (outline) button to visually distinguish it from the primary API token rotation
- Tooltip on the button: *"Generate a read-only token scoped to this application's logs"*
- `has_read_token: true/false` field on the client list response determines whether the button label is "Generate" or "Rotate"
## Acceptance criteria
- [ ] "Generate / Rotate read token" button in client table Actions column
- [ ] `TokenRevealModal` shows correct copy for read vs API token
- [ ] `RotateConfirmModal` shows correct warning for read token rotation
- [ ] Modal cannot be dismissed without clicking the confirmation button
- [ ] `POST /api/clients/{key}/rotate-read-token` called correctly
- [ ] Table reflects `has_read_token` status
Contributor guide
Research direction
Start by reading src/components/clients/ClientTable.tsx, TokenRevealModal.tsx, RotateConfirmModal.tsx, and src/hooks/useClients.ts to trace the existing API-token flow. Confirm the server-side scoped-token dependency and the expected has_read_token response field. Done means the generate/rotate action, token-specific modal copy, confirmation behavior, mutation endpoint, and table status all meet the listed acceptance criteria.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript, vite
- Domain
- api, frontend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100