diff --git a/packages/settings-ui/README.md b/packages/settings-ui/README.md
index f61041aa4..c7daa5565 100644
--- a/packages/settings-ui/README.md
+++ b/packages/settings-ui/README.md
@@ -8,14 +8,16 @@ Presentational primitives come from `@corbits/react-ui`
package holds the workbench-specific section composition, HTTP clients,
and the domain model of which sections exist and who can see them.
-Sections are grouped Account (personal: chat notifications, account,
-connections) and Everyone (account-wide: people, roles, grants, audit) —
-the single-concept collapse of the old Personal/Workspace split, since
+Sections are grouped Account (personal: account) and Everyone
+(account-wide: connections, people, roles, grants, audit) — the
+single-concept collapse of the old Personal/Workspace split, since
there is one workbench per account today. `resolveSettingsSectionGroups`
is the one source of truth a host reads for both the settings stage and
its own section nav, so the two never drift; `insertEveryoneSections` lets
a host splice in its own account-wide sections (e.g. Agents/Skills)
-alongside these.
+alongside these. Notifications and "Your agent" stay out of the registry
+until a preference store backs them (honest absence over draft-only
+toggles).
## Key modules
@@ -25,8 +27,9 @@ alongside these.
- `people-section.tsx` / `roles-section.tsx` / `grants-section.tsx` /
`connections-section.tsx` — the Everyone-group and account-scoped
management surfaces, each with its own API module
-- `account-section.tsx` / `notifications-section.tsx` / `audit-section.tsx`
- — the Account-group surfaces
+- `account-section.tsx` / `audit-section.tsx` — the Account-group and
+ Advanced surfaces (`notifications-section.tsx` remains as a dormant
+ draft until a preference store exists)
- `access.ts` / `tenancy-api.ts` — tenancy-gate resolution and the
principals/roles/grants HTTP client
- `access-policy.tsx` — the grant preview/editor shared by roles and grants
diff --git a/packages/settings-ui/src/index.ts b/packages/settings-ui/src/index.ts
index 3aa036566..a4260aaf2 100644
--- a/packages/settings-ui/src/index.ts
+++ b/packages/settings-ui/src/index.ts
@@ -20,7 +20,8 @@ export {
AppearanceSection,
AgentGeneralSection,
} from "./account-section";
-export { NotificationsSection } from "./notifications-section";
+// NotificationsSection is not exported: it is draft-only and not in the
+// registry (CL-6843). Re-export when a preference store backs it.
export { AuditSection } from "./audit-section";
export { AccessPolicyBlock, AccessPolicyEditor } from "./access-policy";
export {
diff --git a/packages/settings-ui/src/notifications-section.tsx b/packages/settings-ui/src/notifications-section.tsx
index 13b63b3e1..450da26ee 100644
--- a/packages/settings-ui/src/notifications-section.tsx
+++ b/packages/settings-ui/src/notifications-section.tsx
@@ -2,6 +2,15 @@
// inbox / notify stack; these toggles are the operator-facing surface for
// which classes of activity should surface. No per-user preference store
// is mounted yet — draft state only, with an honesty note on save.
+//
+// REMOVED FROM THE SETTINGS REGISTRY (see section-registry.tsx; CL-6843):
+// toggles that save nothing are fake controls, not a settings section —
+// honest absence beats that. Re-add the "chat" section to
+// `SETTINGS_SECTION_GROUPS`'s "account" group only once a per-user
+// preference store exists for these fields and Save actually persists
+// them, not before. (Workbench-scoped mute/mentions prefs live on
+// `@corbits/chat-ui`'s workbench settings surface and already persist —
+// that is a different surface.)
import { Button, SettingsPanel } from "@corbits/react-ui";
import { Check } from "@corbits/icons";
diff --git a/packages/settings-ui/src/section-registry.tsx b/packages/settings-ui/src/section-registry.tsx
index 1c4615b00..f682394e0 100644
--- a/packages/settings-ui/src/section-registry.tsx
+++ b/packages/settings-ui/src/section-registry.tsx
@@ -18,22 +18,13 @@
// `resolveSettingsSectionGroups` — the domain model of "what settings
// exist and who can see them" lives here, not in an app.
-import {
- Bell,
- Key,
- ListBullets,
- Shield,
- Star,
- User,
- Users,
-} from "@corbits/icons";
+import { Key, ListBullets, Shield, Star, User, Users } from "@corbits/icons";
import { AccountSection } from "./account-section";
import type { TenancyAccess } from "./access";
import { AuditSection } from "./audit-section";
import { ConnectionsSection } from "./connections-section";
import { GrantsSection } from "./grants-section";
-import { NotificationsSection } from "./notifications-section";
import { PeopleSection } from "./people-section";
import { RolesSection } from "./roles-section";
import type { SettingsSection, SettingsSectionGroup } from "./shell";
@@ -57,8 +48,10 @@ const SETTINGS_SECTION_GROUPS: readonly SettingsSectionGroupDef[] = [
label: SETTINGS_STRINGS.groupAccountLabel,
// No "Your agent" section here: it has no preference store to back it.
// Re-add only once a hub preference store exists and save actually persists.
- // Account (General) leads — it is the reference's landing section
- // (account card, theme, timezone); notifications follow.
+ // No Notifications ("chat") section either: toggles with no per-user
+ // preference store are fake controls — see notifications-section.tsx
+ // for the re-add condition (CL-6843). Account (General) is the sole
+ // Account-group section until those stores exist.
sections: [
{
id: "account",
@@ -72,12 +65,6 @@ const SETTINGS_SECTION_GROUPS: readonly SettingsSectionGroupDef[] = [
/>
),
},
- {
- id: "chat",
- title: SETTINGS_STRINGS.notificationsSectionTitle,
- icon: Bell,
- render: () => ,
- },
],
},
{
diff --git a/packages/settings-ui/test/section-registry.test.tsx b/packages/settings-ui/test/section-registry.test.tsx
index 7a1c0e5ee..70f63a12a 100644
--- a/packages/settings-ui/test/section-registry.test.tsx
+++ b/packages/settings-ui/test/section-registry.test.tsx
@@ -40,16 +40,16 @@ function ids(groups: ReturnType) {
}
describe("resolveSettingsSectionGroups", () => {
- test("Account's Notifications and Account sections are always full; gated Everyone sections are absent, not disabled", () => {
+ test("Account's Account section is always full; gated Everyone sections are absent, not disabled", () => {
expect(ids(resolveSettingsSectionGroups(denied))).toEqual([
- { id: "account", sections: ["account", "chat"] },
+ { id: "account", sections: ["account"] },
{ id: "everyone", sections: ["audit"] },
]);
});
test("an allowed gate adds its section in registry order", () => {
expect(ids(resolveSettingsSectionGroups(allowed))).toEqual([
- { id: "account", sections: ["account", "chat"] },
+ { id: "account", sections: ["account"] },
{
id: "everyone",
sections: ["connections", "people", "roles", "grants", "audit"],
@@ -65,7 +65,7 @@ describe("resolveSettingsSectionGroups", () => {
credentials: "denied",
};
expect(ids(resolveSettingsSectionGroups(loading))).toEqual([
- { id: "account", sections: ["account", "chat"] },
+ { id: "account", sections: ["account"] },
{ id: "everyone", sections: ["grants", "audit"] },
]);
});
@@ -93,6 +93,17 @@ describe("resolveSettingsSectionGroups", () => {
}
});
+ test("never registers the notifications section — no preference store exists to back it yet", () => {
+ for (const access of [denied, allowed]) {
+ const account = resolveSettingsSectionGroups(access).find(
+ (group) => group.id === "account",
+ );
+ expect(account?.sections.map((section) => section.id)).not.toContain(
+ "chat",
+ );
+ }
+ });
+
test("every section carries a leading icon for a host's own nav", () => {
for (const group of resolveSettingsSectionGroups(allowed)) {
for (const section of group.sections) {
@@ -114,7 +125,7 @@ describe("insertEveryoneSections", () => {
extra,
);
expect(ids(groups)).toEqual([
- { id: "account", sections: ["account", "chat"] },
+ { id: "account", sections: ["account"] },
{ id: "everyone", sections: ["agents", "skills", "audit"] },
]);
});
@@ -125,10 +136,7 @@ describe("insertEveryoneSections", () => {
extra,
);
const account = groups.find((group) => group.id === "account");
- expect(account?.sections.map((section) => section.id)).toEqual([
- "account",
- "chat",
- ]);
+ expect(account?.sections.map((section) => section.id)).toEqual(["account"]);
});
test("is a no-op when there is nothing to insert", () => {