infisical/infisical
Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.
30 files reviewed·July 25, 2026
More findings
Verdict
Six copy-pasted Switch blocks reveal a settings screen built by repetition, not componentization, and the cracks show at exactly the moments that matter most. High-consequence toggles like admin grants and login-method disabling fire instantly with no confirmation, turning a flat UI pattern into a real lockout risk.
Files Rams reviewed
frontend/src/pages/pam/components/policyEditors/index.tsx
frontend/src/pages/admin/AccessManagementPage/components/AddServerAdminModal.tsx
frontend/src/pages/admin/AuthenticationPage/components/AuthenticationPageForm.tsx
frontend/src/pages/admin/CachingPage/components/CachingPageForm.tsx
frontend/src/pages/admin/EncryptionPage/components/EncryptionPageForm.tsx
frontend/src/pages/admin/EnvironmentPage/components/EnvironmentPageForm.tsx
frontend/src/pages/admin/GeneralPage/components/GeneralPageForm.tsx
frontend/src/pages/admin/GeneralPage/components/UsageReportSection.tsx
frontend/src/pages/admin/IntegrationsPage/components/IntegrationsPageForm.tsx
frontend/src/pages/admin/IntegrationsPage/components/MicrosoftTeamsIntegrationForm.tsx
frontend/src/pages/admin/IntegrationsPage/components/SlackIntegrationForm.tsx
frontend/src/pages/admin/ResourceOverviewPage/components/AddOrganizationModal.tsx
frontend/src/pages/admin/ResourceOverviewPage/components/EmailDomainsTable.tsx
frontend/src/pages/admin/ResourceOverviewPage/components/MachineIdentitiesTable.tsx
frontend/src/pages/admin/SignUpPage/components/AdminSignUpForm.tsx
frontend/src/pages/ai/MCPEndpointDetailPage/components/MCPEndpointConnectedServersSection.tsx
frontend/src/pages/ai/MCPEndpointDetailPage/components/MCPEndpointConnectionSection.tsx
frontend/src/pages/ai/MCPEndpointDetailPage/components/MCPEndpointDetailsSection.tsx
frontend/src/pages/ai/MCPEndpointDetailPage/components/MCPEndpointFiltersSection.tsx
frontend/src/pages/ai/MCPEndpointDetailPage/components/MCPEndpointToolSelectionSection.tsx
frontend/src/pages/ai/MCPEndpointDetailPage/components/MCPEndpointUsageStatisticsSection.tsx
frontend/src/pages/ai/MCPEndpointDetailPage/components/PiiFilterConfigModal.tsx
frontend/src/pages/ai/MCPPage/components/MCPActivityLogsTab/MCPActivityLogsDateFilter.tsx
frontend/src/pages/ai/MCPPage/components/MCPActivityLogsTab/MCPActivityLogsFilter.tsx
frontend/src/pages/ai/MCPPage/components/MCPActivityLogsTab/MCPActivityLogsTab.tsx
frontend/src/pages/ai/MCPPage/components/MCPActivityLogsTab/MCPActivityLogsTableRow.tsx
frontend/src/pages/ai/MCPPage/components/MCPEndpointsTab/AddMCPEndpointModal/AddMCPEndpointModal.tsx
frontend/src/pages/ai/MCPPage/components/MCPEndpointsTab/EditMCPEndpointModal.tsx
frontend/src/pages/ai/MCPPage/components/MCPEndpointsTab/MCPEndpointList.tsx
frontend/src/pages/ai/MCPPage/components/MCPEndpointsTab/MCPEndpointRow.tsx
UX
frontend/src/pages/admin/AccessManagementPage/components/AddServerAdminModal.tsx:67
Granting server admin access has no confirmation step before it fires
The "Grant" button submits onSubmit directly, calling grantAdmin.mutateAsync(user.id) with no intermediate confirmation dialog. Elevating a user to server admin is one of the highest-privilege actions in the app, yet it fires on a single click the moment the form validates.
Why it matters
A mis-click or a wrong selection in the user search grants full server admin permissions instantly, with no chance to catch the mistake before it takes effect.
Fix
Require an explicit confirmation step before executing irreversible or high-privilege mutations.
const onSubmit = async ({ user }: FormData) => {
await grantAdmin.mutateAsync(user.id);
createNotification({
type: "success",
text: "Successfully granted server admin status"
});
onClose();
};const onSubmit = async ({ user }: FormData) => {
if (!window.confirm(`Grant server admin access to ${getUserLabel(user)}?`)) return;
await grantAdmin.mutateAsync(user.id);
createNotification({
type: "success",
text: "Successfully granted server admin status"
});
onClose();
};frontend/src/pages/admin/AuthenticationPage/components/AuthenticationPageForm.tsx:86
"At least one login method should be enabled" error hides in a toast
In AuthenticationPageForm's onAuthFormSubmit, disabling every login switch produces createNotification({ type: 'error', text: 'At least one login method should be enabled.' }) as a global toast, with no inline error rendered near the Email, Google, Github, Gitlab, SAML, OIDC, or LDAP Switch rows that caused it.
Why it matters
The toast disappears after a few seconds and gives no visual link back to which control needs to change, so the admin has to guess which switch to re-enable.
Fix
Attach validation errors to the specific form field via react-hook-form's setError so the message renders inline where the user is looking.
if (!enabledMethods.length) {
createNotification({
type: "error",
text: "At least one login method should be enabled."
});
return;
}if (!enabledMethods.length) {
setError("isEmailEnabled", {
message: "At least one login method must stay enabled."
});
return;
}frontend/src/pages/admin/AuthenticationPage/components/AuthenticationPageForm.tsx:234
Disabling a login method locks out relying users with no confirmation
The "Save" button in AuthenticationPageForm submits directly with isDisabled={isSubmitting || !isDirty}, no confirmation step, even though unchecking a switch like GitHub or SAML and saving immediately removes that login path for every org user who depends on it.
Why it matters
An admin who toggles off a login method by mistake locks out all users relying on that provider the instant Save completes, with no warning before the change takes effect.
Fix
Confirm destructive or access-affecting changes before submit when the diff removes an enabled login method.
<Button
className="mt-2"
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting || !isDirty}
>
Save
</Button><Button
className="mt-2"
type="submit"
isLoading={isSubmitting}
isDisabled={isSubmitting || !isDirty}
onClick={(e) => {
if (!window.confirm("Disabling a login method may lock out users who rely on it. Continue?")) {
e.preventDefault();
}
}}
>
Save
</Button>frontend/src/pages/admin/AccessManagementPage/components/AddServerAdminModal.tsx:110
Cancel button defaults to type submit inside the grant-admin form
In AddServerAdminModal's Content form, the "Cancel" button at line 110 has no explicit type attribute. Inside a <form>, buttons default to type='submit', so this button sits alongside the real "Grant" submit button with the same implicit behavior.
Why it matters
A click on "Cancel" can submit the form and grant server admin access instead of closing the modal, the opposite of what the label promises.
Fix
Set explicit type='button' on every in-form action that is not meant to submit.
<Button onClick={() => onClose()} variant="plain" colorSchema="secondary">
Cancel
</Button><Button type="button" onClick={() => onClose()} variant="plain" colorSchema="secondary">
Cancel
</Button>Components
frontend/src/pages/admin/AuthenticationPage/components/AuthenticationPageForm.tsx:114
Six copy-pasted Switch blocks mean every fix repeats six times
AuthenticationPageForm repeats the identical Controller + FormControl + Switch structure for isEmailEnabled, isGoogleEnabled, isGithubEnabled, isGitlabEnabled, isSamlEnabled, and isOidcEnabled, differing only in name, id, and label text (starting at line 114 with "Email").
Why it matters
Any future change to error display, spacing, or accessibility on these switches has to be applied six separate times, and missing one creates visible drift between login methods.
Fix
Extract the repeated Controller/Switch pattern into a single parameterized component.
<Controller
control={control}
name="isEmailEnabled"
render={({ field, fieldState: { error } }) => {
return (
<FormControl isError={Boolean(error)} errorText={error?.message}>
<Switch
id="email-enabled"
onCheckedChange={(value) => field.onChange(value)}
isChecked={field.value}
>
<p className="w-24">Email</p>
</Switch>
</FormControl>
);
}}
/>const LoginMethodSwitch = ({ control, name, id, label }: LoginMethodSwitchProps) => (
<Controller
control={control}
name={name}
render={({ field, fieldState: { error } }) => (
<FormControl isError={Boolean(error)} errorText={error?.message}>
<Switch id={id} onCheckedChange={field.onChange} isChecked={field.value}>
<p className="w-24">{label}</p>
</Switch>
</FormControl>
)}
/>
);
<LoginMethodSwitch control={control} name="isEmailEnabled" id="email-enabled" label="Email" />Accessibility
Typography
Color
Spacing
Motion
Craft
Working well
- The FilterableSelect wires isLoading from comparing searchUserFilter to debouncedSearchTerm, giving accurate loading feedback during the debounce window.
- The Invalidate button is correctly disabled via isDisabled={!user.superAdmin || isInvalidating}, preventing duplicate submissions while a cache job runs.
- The Select is only rendered once `rootKmsDetails` is available (`{!!rootKmsDetails && ...}`), avoiding a flash of an empty control before data loads.
- Disabling the Save button on `isSubmitting || !isDirty` correctly prevents redundant submits and no-op saves in one condition.
Scored July 25, 2026 with Rams Engine v0.0.3 · Engine changelog
First scored July 9, 2026: 59/100. This rescore on v0.0.3: 88/100.
This page is an automated design review of infisical/infisical’s UI code: 30 files read against 291 versioned rules covering accessibility, color, typography, spacing, components, UX, motion, and craft. The score is out of 100; confirmed criticals cap it — one at 59, two at 49, three or more at 39.
More design scores
Score your own repo.
Free on public repos, no account. The same engine that scored this page reads your UI code and mints a score page like this one.
Public repos only. The full engine reviews the UI code and mints a public score page — we email you the link too. Already-scored repos open instantly.