Area / route
A batch of confirmed low-severity settings (account/org/connections/api) defects, each independently fixable. Grouped as polish; itemized below.
Sites
- [101] Custom-instructions client schema validates length but not the backend's illegal-character rule (validation-parity gap)
- Evidence: personalization-settings.tsx:375-381
z.object({ customInstructions: z.string().max(CUSTOM_INSTRUCTIONS_MAX_CHARS) }) (no illegal-char refine) vs convex/user_preferences/mutations.ts:39-49 if (CUSTOM_INSTRUCTIONS_ILLEGAL_RE.test(normalized)) throw new ConvexError({ code: 'invalid', ... }).
- [102] Team-edit member checklist silently refuses to uncheck the last member with no user feedback
- Evidence: team-edit-dialog.tsx:86-97
setSelectedMemberIds((prev) => { ... if (next.size <= 1) return prev; ... }) (silent) + convex/team_members/mutations.ts:164-168 throw new Error('Cannot remove the last team member. Delete the team instead.').
- [104] Integration Disconnect shows no loading state during the in-flight action (isSubmitting hardcoded false; spinner + ConfirmDialog isLoading are dead)
- Evidence: use-integration-manage.ts:199
const isSubmitting = false; and :306 busy = isSubmitting || isTesting || isSavingOAuth2 || isApplyingUpdate; integration-panel.tsx:222-231 button spinner gated on manage.isSubmitting, :282 ConfirmDialog isLoading={manage.isSubmitting}, :283-286 onConfirm fires async then closes immediately.
- [105] integrations route accepts ?section=apps in its search schema but it is never read (silently inert dead surface)
- Evidence: integrations.tsx:28
section: z.enum(['apps', 'mcp-servers']).optional(); :44-49 beforeLoad only handles 'mcp-servers'; no other reference to search.section in the file.
- [108] MCP server "Name" allows invalid single-character/uppercase slugs (client) and has no server-side validation at all
- Evidence: services/platform/app/features/settings/mcp-servers/components/mcp-server-form.tsx:137 (name.length > 1 guard); services/platform/convex/mcp_servers/public_mutations.ts:66,98; services/platform/convex/mcp_servers/mutations.ts:53-54
Notes
Per item: [101] mirror the backend illegal-char rule client-side via a .refine() (normalize CRLF identically); [102] disable the sole-member checkbox + add an explanatory hint key; [104] surface a real in-flight isSubmitting (and keep the ConfirmDialog open until the await resolves); [105] drop 'apps' from the integrations search enum (or handle it); [108] drop the name.length>1 carve-out and add backend validation + per-org uniqueness on the MCP create/update path. [101] distinct from #1991; [105] distinct from #1979/#1982; [108] distinct from #1991.
Filed by an automated manual-review pass (live browser QA + a 25-agent code-grounded audit, each finding adversarially verified). Deduped against open issues (incl. #1972–#1999, settings/forms epic #1941–#1966, audit cluster #1842–#1846) and recently-closed issues.
Area / route
A batch of confirmed low-severity settings (account/org/connections/api) defects, each independently fixable. Grouped as polish; itemized below.
Sites
z.object({ customInstructions: z.string().max(CUSTOM_INSTRUCTIONS_MAX_CHARS) })(no illegal-char refine) vs convex/user_preferences/mutations.ts:39-49if (CUSTOM_INSTRUCTIONS_ILLEGAL_RE.test(normalized)) throw new ConvexError({ code: 'invalid', ... }).setSelectedMemberIds((prev) => { ... if (next.size <= 1) return prev; ... })(silent) + convex/team_members/mutations.ts:164-168throw new Error('Cannot remove the last team member. Delete the team instead.').const isSubmitting = false;and :306busy = isSubmitting || isTesting || isSavingOAuth2 || isApplyingUpdate; integration-panel.tsx:222-231 button spinner gated onmanage.isSubmitting, :282 ConfirmDialogisLoading={manage.isSubmitting}, :283-286 onConfirm fires async then closes immediately.section: z.enum(['apps', 'mcp-servers']).optional(); :44-49 beforeLoad only handles 'mcp-servers'; no other reference tosearch.sectionin the file.Notes
Per item: [101] mirror the backend illegal-char rule client-side via a .refine() (normalize CRLF identically); [102] disable the sole-member checkbox + add an explanatory hint key; [104] surface a real in-flight isSubmitting (and keep the ConfirmDialog open until the await resolves); [105] drop
'apps'from the integrations search enum (or handle it); [108] drop thename.length>1carve-out and add backend validation + per-org uniqueness on the MCP create/update path. [101] distinct from #1991; [105] distinct from #1979/#1982; [108] distinct from #1991.Filed by an automated manual-review pass (live browser QA + a 25-agent code-grounded audit, each finding adversarially verified). Deduped against open issues (incl. #1972–#1999, settings/forms epic #1941–#1966, audit cluster #1842–#1846) and recently-closed issues.