Skip to content

feat: add user secrets management page#25371

Merged
dylanhuff-at-coder merged 16 commits into
mainfrom
dylan/plat-102-user-secrets-settings-page
May 26, 2026
Merged

feat: add user secrets management page#25371
dylanhuff-at-coder merged 16 commits into
mainfrom
dylan/plat-102-user-secrets-settings-page

Conversation

@dylanhuff-at-coder
Copy link
Copy Markdown
Contributor

@dylanhuff-at-coder dylanhuff-at-coder commented May 14, 2026

Adds the account settings UI for managing user secrets, including the table, add/edit/delete dialog, Storybook coverage, and route/sidebar entry.

Also updates the shared FeatureStageBadge early-access variant with dedicated Early Access styling, sizing, and label casing for the Secrets page.

Stacked on #25370.

This PR was generated by Coder Agents.

Copy link
Copy Markdown
Contributor Author

dylanhuff-at-coder commented May 14, 2026

@github-actions
Copy link
Copy Markdown

Docs preview

📖 View docs preview for docs/user-guides/user-secrets.md

@dylanhuff-at-coder dylanhuff-at-coder force-pushed the dylan/plat-102-user-secrets-client-utilities branch from afe1534 to d6ed353 Compare May 14, 2026 21:57
@dylanhuff-at-coder dylanhuff-at-coder force-pushed the dylan/plat-102-user-secrets-settings-page branch 4 times, most recently from 6ca38b7 to 8f346c5 Compare May 19, 2026 15:50
@dylanhuff-at-coder dylanhuff-at-coder force-pushed the dylan/plat-102-user-secrets-client-utilities branch from 2ed690a to 3515ca7 Compare May 19, 2026 15:50
Base automatically changed from dylan/plat-102-user-secrets-client-utilities to main May 19, 2026 16:30
@dylanhuff-at-coder dylanhuff-at-coder force-pushed the dylan/plat-102-user-secrets-settings-page branch from 8f346c5 to 57e2ed5 Compare May 19, 2026 16:37
@dylanhuff-at-coder
Copy link
Copy Markdown
Contributor Author

/coder-agents-review

Copy link
Copy Markdown
Contributor

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well-structured secrets management page with thorough Storybook coverage (15 stories, 14 with play functions). The component reuse is good: Dialog, Table, Badge, SettingsHeader, ErrorAlert, etc. The return-focus management for dialogs is genuine accessibility work. The FeatureStageBadge refactor is safe for existing consumers (verified all beta xs paths are unchanged).

1 P2, 8 P3, 7 Nit.

The P2 is a security misrepresentation: the dialog says "Secrets are encrypted" but this is only true with the enterprise dbcrypt layer. AGPL deployments store values in plaintext. A user reading this claim might skip using an external vault.

The most convergent P3 (7/19 reviewers flagged independently): the three new Promise wrappers around mutate() in SecretsPage.tsx. Every sibling page in UserSettingsPage/ uses mutateAsync with try/catch. The manual wrappers produce correct behavior but add ~45 lines of indirection that mutateAsync eliminates. This refactor also subsumes the unnecessary useCallback wrappers and the onMutationError helper.

A related P3: the create/update error path fires both a toast AND inline form errors for the same failure. The mutateAsync refactor is the right time to decide which channel owns error display.

"If the user presses Escape while the form is submitting, the dialog closes and the Radix portal unmounts the form. The mutation continues in the background. On error, the toast fires but the form-level error display is lost because the component is unmounted." (Mafuuu)

Process note: commit 939dc440 subject "address user secrets review feedback" tells a reader nothing about what changed. Good subjects elsewhere in the branch ("preserve secret API field errors", "use backend secret validation").

🤖 This review was automatically generated with Coder Agents.

Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretDialog.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsPage.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsPage.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretDialog.tsx
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretDialog.tsx
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsTable.tsx
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsPageView.stories.tsx Outdated
Comment thread site/src/components/FeatureStageBadge/FeatureStageBadge.tsx Outdated
Comment thread site/src/index.css Outdated
Use mutateAsync for secret mutations, keep create and update errors inline, and keep delete failures toasted.

Prevent closing the secret dialog while submitting, tighten warning copy, and expand Storybook coverage for dialog edge cases.

Align feature badge and secret type labels without changing layout.
@dylanhuff-at-coder dylanhuff-at-coder marked this pull request as ready for review May 20, 2026 00:53
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsTable.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretDialog.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretDialog.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretDialog.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsPageView.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretDialog.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsPageView.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretDialog.tsx
Use mutateAsync for secret mutations, keep create and update errors inline, and keep delete failures toasted.

Prevent closing the secret dialog while submitting, tighten warning copy, and expand Storybook coverage for dialog edge cases.

Align feature badge and secret type labels without changing layout.
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretDialog.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretDialog.tsx Outdated
autoComplete="off"
className="placeholder:text-content-disabled"
data-lpignore="true"
data-1p-ignore="true"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the thinking behind telling password mangers to ignore this field? I use a password manager that can fill in things like this when configured.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field is file path which seems less likely to be filled in by password managers, value (which is below) won't be ignored by password managers. Tracy and I were both having the experience of password managers being overly eager to fill in all the fields in this pop-out, which was a little annoying, so I added password manager ignore to a few fields to help

Copy link
Copy Markdown
Contributor

@zedkipp zedkipp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I can give a meaningful deep review of the frontend code, so you'll want some frontend folks eyes on this. I did some manual testing and it looks good functionality wise.

@coder-tasks
Copy link
Copy Markdown
Contributor

coder-tasks Bot commented May 22, 2026

Documentation Check

Updates Needed

  • docs/user-guides/user-secrets.md - The existing docs cover only CLI and REST API usage (coder secret create, coder secret update, etc.). This PR adds a web UI for managing secrets via Account Settings > Secrets. The docs should mention that secrets can also be created, edited, and deleted from the Coder dashboard, with a brief description of how to navigate there (e.g., click your avatar > Account > Secrets).

Automated review via Coder Agents

Mention dashboard management in user secrets docs and wait for the Clear button to become visible in the Storybook interaction to avoid dialog animation races.
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsTable.tsx Outdated
Copy link
Copy Markdown
Contributor

@jakehwll jakehwll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Big PR so I'm going to do another pass later 🙂

Nothing too scary, but this is a few pointers to get this closer

};

const infoText = "Secret values cannot be retrieved once saved.";
const savedSecretValueDisplay = "••••••••••••••••••••";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whynot just render the value as a type="password" ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I did this so since type="password" was exacerbating the over eager password manager suggestions that we were seeing

Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretDialog.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsPage.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsPageView.stories.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsTable.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsTable.tsx
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsTable.tsx Outdated
Comment thread site/src/pages/UserSettingsPage/SecretsPage/SecretsTable.tsx Outdated
Comment thread site/src/index.css Outdated
Comment on lines +112 to +116
useEffect(() => {
if (open) {
setClearValueRequested(false);
}
}, [open]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love this use of useEffect to keep another value in sync..

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, I removed the mirrored state/effect and made isShowingSavedValue derived from the current props plus a small piece of interaction state. The field remounts when the edit dialog opens, so the hidden-saved-value state resets without needing an effect to keep it in sync.

@dylanhuff-at-coder dylanhuff-at-coder merged commit 7887cff into main May 26, 2026
30 checks passed
@dylanhuff-at-coder dylanhuff-at-coder deleted the dylan/plat-102-user-secrets-settings-page branch May 26, 2026 18:51
@github-actions github-actions Bot locked and limited conversation to collaborators May 26, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants