diff --git a/packages/settings-ui/src/strings.ts b/packages/settings-ui/src/strings.ts index 52759b5df..bdc1ac69e 100644 --- a/packages/settings-ui/src/strings.ts +++ b/packages/settings-ui/src/strings.ts @@ -19,7 +19,7 @@ export const SETTINGS_STRINGS = { notificationsRoutineFail: "Failed deliveries", notificationsSaveAction: "Save", notificationsSaveHonesty: - "Draft only — per-user notification prefs are not stored on the hub yet.", + "Draft only — notification choices aren't saved yet.", settingsSavedToast: "Settings saved", @@ -27,12 +27,12 @@ export const SETTINGS_STRINGS = { benchNoneSelectedDescription: "Choose a workbench from the switcher first.", accountSectionTitle: "General", - accountSectionDescription: "How the hub identifies you.", + accountSectionDescription: "Your name and email on this workbench.", accountNameLabel: "Name", accountEmailLabel: "Email", accountLoadError: "your account", accountReadOnlyNote: - "Managed through the authentication API; editing from this screen has not been built yet.", + "These details come from how you sign in. Editing them here isn't available yet.", accountSignOutAction: "Sign out", accountDetailsHeading: "Account details", accountCopyEmailAction: "Copy email", @@ -75,9 +75,9 @@ export const SETTINGS_STRINGS = { peopleRemoveError: "Couldn't remove that person — try again.", peopleUnnamedAgent: "Unnamed agent", peopleRoleNone: "none", - peopleKindUser: "user", - peopleKindAgent: "agent", - peopleKindWorkflow: "workflow", + peopleKindUser: "Person", + peopleKindAgent: "Agent", + peopleKindWorkflow: "Workflow", peopleRoleChangeError: "Couldn't change that person's role — try again.", peopleLastOwnerError: "This workbench needs at least one owner — make someone else an owner first.", @@ -112,7 +112,7 @@ export const SETTINGS_STRINGS = { accessPolicyNote: "Closed by default: no open signup, no self-serve sub-workbenches. These settings apply to this workbench.", accessPolicyEnvOverrideNotice: - "The operator has sign-up switched off at the server level, so people still can't create an account yet — even though this setting would otherwise allow it. Ask whoever manages this deployment to enable self-signup.", + "Sign-up is switched off at a higher level, so people still can't create an account yet — even though this setting would otherwise allow it. Ask whoever controls this install's environment to enable self-signup.", rolesSectionTitle: "Roles", rolesSectionDescription: @@ -198,7 +198,7 @@ export const SETTINGS_STRINGS = { connectionsStatusNeedsAttention: "Needs attention", connectionsStatusNotConfigured: "Needs setup", connectionsNotConfiguredHint: - "An operator needs to register an OAuth app for this connector before anyone can connect it.", + "An OAuth app needs to be registered for this connector before anyone can connect it.", connectionsConnectAction: "Connect", connectionsReconnectAction: "Reconnect", connectionsDisconnectAction: "Disconnect", @@ -208,16 +208,16 @@ export const SETTINGS_STRINGS = { connectionsDefaultModelLabel: "Default model:", connectionsSetDefaultModelError: "Couldn't set the default model — try again.", - connectionsPinnedByPrefix: "Used by workflows: ", - connectionsPinnedByNone: "Available to any workflow", + connectionsPinnedByPrefix: "Used by: ", + connectionsPinnedByNone: "Not pinned by any workflow", connectionsPinnedByApproximationNote: - "Based on each workflow's declared tool-package pins, not a live query against deployed definitions — may lag a workflow's actual tool usage.", + "Based on declared pins, not live usage — may lag actual tool usage.", connectionsDialogConnectTitle: (name: string) => `Connect ${name}`, connectionsDialogReconnectTitle: (name: string) => `Reconnect ${name}`, connectionsDialogDescription: "Sealed on save — this key is never shown again after create. A bad key never gets saved; connecting surfaces the problem right here.", connectionsDialogUrlDescription: - "The base address of the instance to connect. A bad address never gets saved; connecting surfaces the problem right here.", + "The base address of the service to connect. A bad address never gets saved; connecting surfaces the problem right here.", connectionsKeyLabel: "API key", connectionsUrlLabel: "Base URL", connectionsConnectDialogAction: "Connect", diff --git a/packages/settings-ui/test/grants-section.test.tsx b/packages/settings-ui/test/grants-section.test.tsx index 74fcedde7..6744d9c75 100644 --- a/packages/settings-ui/test/grants-section.test.tsx +++ b/packages/settings-ui/test/grants-section.test.tsx @@ -16,6 +16,7 @@ import type { Root } from "react-dom/client"; import { renderToStaticMarkup } from "react-dom/server"; import { CreateGrantDialog, GrantsTable } from "../src/grants-section"; +import { PRINCIPAL_KIND_LABEL, PRINCIPAL_KIND_ORDER } from "../src/identity"; const timestamps = { createdAt: "2026-01-01T00:00:00.000Z", @@ -130,10 +131,11 @@ describe("CreateGrantDialog", () => { act(() => (principalCard as HTMLButtonElement).click()); const optgroups = [...document.body.querySelectorAll("optgroup")]; - expect(optgroups.map((group) => group.label)).toEqual([ - "user", - "agent", - "workflow", + expect(optgroups.map((group) => group.label)).toEqual( + PRINCIPAL_KIND_ORDER.map((kind) => PRINCIPAL_KIND_LABEL[kind]), + ); + expect(optgroups.map((group) => group.label)).not.toEqual([ + ...PRINCIPAL_KIND_ORDER, ]); } finally { act(() => root.unmount()); diff --git a/packages/settings-ui/test/identity.test.ts b/packages/settings-ui/test/identity.test.ts index ea843a8ae..c36379abd 100644 --- a/packages/settings-ui/test/identity.test.ts +++ b/packages/settings-ui/test/identity.test.ts @@ -53,10 +53,13 @@ describe("principalLabel", () => { // person's account. Every picker groups or annotates by this shared label. describe("PRINCIPAL_KIND_LABEL", () => { test("covers every kind in PRINCIPAL_KIND_ORDER with a distinct, honest label", () => { + expect(PRINCIPAL_KIND_ORDER).toEqual(["user", "agent", "workflow"]); const labels = PRINCIPAL_KIND_ORDER.map( (kind) => PRINCIPAL_KIND_LABEL[kind], ); - expect(labels).toEqual(["user", "agent", "workflow"]); + expect(labels).toHaveLength(PRINCIPAL_KIND_ORDER.length); expect(new Set(labels).size).toBe(labels.length); + expect(labels).toEqual(["Person", "Agent", "Workflow"]); + expect(labels).not.toEqual([...PRINCIPAL_KIND_ORDER]); }); }); diff --git a/packages/settings-ui/test/roles-section.test.tsx b/packages/settings-ui/test/roles-section.test.tsx index f27601e71..9366dcb82 100644 --- a/packages/settings-ui/test/roles-section.test.tsx +++ b/packages/settings-ui/test/roles-section.test.tsx @@ -6,6 +6,7 @@ import { describe, expect, test } from "bun:test"; import { renderToStaticMarkup } from "react-dom/server"; +import { PRINCIPAL_KIND_LABEL, PRINCIPAL_KIND_ORDER } from "../src/identity"; import { RoleAssignments } from "../src/roles-section"; const timestamps = { @@ -56,7 +57,10 @@ describe("RoleAssignments picker", () => { const groupOrder = [...markup.matchAll(/ match[1], ); - expect(groupOrder).toEqual(["user", "agent", "workflow"]); + expect(groupOrder).toEqual( + PRINCIPAL_KIND_ORDER.map((kind) => PRINCIPAL_KIND_LABEL[kind]), + ); + expect(groupOrder).not.toEqual([...PRINCIPAL_KIND_ORDER]); }); test("omits an empty kind group entirely rather than an empty optgroup", () => { @@ -71,6 +75,7 @@ describe("RoleAssignments picker", () => { const groupOrder = [...markup.matchAll(/ match[1], ); - expect(groupOrder).toEqual(["user"]); + expect(groupOrder).toEqual([PRINCIPAL_KIND_LABEL.user]); + expect(groupOrder).not.toEqual(["user"]); }); }); diff --git a/packages/settings-ui/test/strings.test.ts b/packages/settings-ui/test/strings.test.ts new file mode 100644 index 000000000..9eae3fd4d --- /dev/null +++ b/packages/settings-ui/test/strings.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, test } from "bun:test"; + +import { SETTINGS_STRINGS } from "../src/strings"; + +function stringValues(value: unknown): string[] { + if (typeof value === "string") return [value]; + if (typeof value === "function" || value === null || value === undefined) { + return []; + } + if (typeof value === "object") { + return Object.values(value).flatMap(stringValues); + } + return []; +} + +describe("SETTINGS_STRINGS", () => { + test("person-facing values drop intern chrome", () => { + const values = stringValues(SETTINGS_STRINGS); + expect(values.length).toBeGreaterThan(0); + for (const text of values) { + expect(text).not.toMatch(/auth API/i); + expect(text).not.toMatch(/\bhub\b/i); + expect(text).not.toMatch(/\bInference\b/); + expect(text).not.toMatch(/\boperators?\b/i); + expect(text).not.toMatch(/\bdeployments?\b/i); + } + }); +});