Skip to content

Commit 8cb8c7f

Browse files
fix(platform-objects): name each Setup settings entry as the hub does; label notification and audit options (#28062)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} --> _Requested by **Elon** · [project thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DFGYFLQXxGe8p4z4ZkYBq7Y)_ domain:server#4 · os-elon-musk · session_016WV4cxh364AJYtdpWoPiHV Fixes #27854 Refs #27855 Clause-②: no Metadata-protocol: none ## 维护者速读 - 改了什么:Setup 侧栏的设置入口改用设置总览页(All Settings)的卡片标题,四种语言一致(英文 "Email" 改为 "Mail Delivery",中文「邮件」改为「邮件投递」「公司信息」改为「公司」等),并补上 SMS Delivery 和 Data Lifecycle 两个入口;通知事件的严重程度显示 Info / Warning / Critical,来源对象显示对象名称而非 `sys_approval_request`;审计日志的动作(含 System Overview 的 "Audit Events by Action")在英文下显示 "Config Change" 而非 `config_change`。 - 为什么改:管理员在侧栏和总览页看到同一页面两个名字,两个设置页从侧栏到不了,几个页面直接显示内部代码(#27521 第 3、4 行)。 - 风险与回滚:只改显示文字、选项标签和导航入口,存储值与可接受的输入都不变;新增的两个入口要求 `manage_platform_settings`,与对应设置页的读权限一致。回滚即 revert 本 PR。 - 先看:`packages/platform-objects/src/apps/setup-nav.contributions.ts`、`packages/services/service-settings/src/setup-nav-hub-parity.test.ts`(侧栏对总览页的防漂移测试)、`packages/plugins/plugin-audit/src/objects/sys-audit-log.object.ts`。 - 两分钟验证:`pnpm --filter @objectstack/service-settings exec vitest run src/setup-nav-hub-parity.test.ts`,预期 9 passed(在 main 上 6 个红)。 - 需要你做的:无,席位落地。通知主题(topic)可读化未做:主题是开放词表,平台没有主题名称来源,#27855 保持打开。 ## What changes **Setup sidebar ↔ settings hub (#27854).** One name per settings page, one set of pages. - `setup-nav.contributions.ts`: `nav_settings_mail` is labelled "Mail Delivery" (was "Email"). New entries `nav_settings_sms` ("SMS Delivery", after mail) and `nav_settings_lifecycle` ("Data Lifecycle", after Knowledge), both `requiredPermissions: ['manage_platform_settings']`, the read permission of their namespaces. - Translations (`apps/translations/{en,zh-CN,ja-JP,es-ES}.ts`): each settings entry takes the hub card's title in that locale. zh-CN / ja-JP: company 公司信息 / 会社情報 → 公司 / 会社, mail 邮件 / メール → 邮件投递 / メール配信. es-ES: mail Correo → Envío de correo, storage and feature flags take the hub's wording. The two new entries are translated; the lifecycle wording reuses the object form's existing "Data Lifecycle" term in each locale. The mail entry's recorded source hashes are refreshed with its re-translation (the en source changed), and the two new entries record theirs. - Drift pin, `packages/services/service-settings/src/setup-nav-hub-parity.test.ts` (it lives there because service-settings depends on platform-objects, so the reverse import would be a cycle). It boots `SettingsServicePlugin` with the bundled manifests, registers `lifecycleSettingsManifest` the way `ObjectQLPlugin` does, folds the Setup tree through the real registry (so the Branding entry this package contributes counts), and asserts: every hub namespace has exactly one sidebar entry and no entry opens an unlisted page; the en label equals the hub title; each translated locale's label equals the hub's translated title wherever the hub has one; and the namespaces with no translated hub title are exactly `['lifecycle']`. **Notification Events and the audit action (#27855, partly).** - `audit/sys-notification.object.ts`: `severity` options are labelled Info / Warning / Critical over the same `info` / `warning` / `critical` values. `source_object` declares `widget: 'object-ref'` (the sharing-rule pattern), so the console draws the object's label; the field stays text and nothing but `NotificationService` writes it (`apiMethods: ['get', 'list']`). - `plugin-audit/src/objects/sys-audit-log.object.ts`: every `action` option carries a label ("Config Change", "Login Failed", …), stored values unchanged. The "Audit Events by Action" chart reads these: `resolveDimensionLabels` (`@objectstack/service-analytics`) resolves a dimension through the field's options whatever the dimension's `type`, so `system.datasets.ts` needs no change. The bare-array `Field.select` shorthand had made each label the code; zh-CN / ja-JP / es-ES already carried words, only en showed codes. - Regenerated: `platform-objects/src/apps/translations/en.objects.generated.ts` (severity), `plugin-audit/src/translations/en.objects.generated.ts` (action), by `node scripts/check-i18n-bundles.mjs --write`; no translated-locale value moved. **Not in this PR.** - Readable notification topic: `topic` is an open vocabulary (a flow's notify step names any topic; about 30 distinct topics are emitted) and no topic catalog with labels exists. A `select` would refuse unknown topics, a narrowing. Left out by the seat's ruling; #27855 stays open for it. - `identity/sys-user.object.ts` (`env_native` identity-source label, the third bullet of #27855): belongs with the `sys_user` rows (#27858) and is not touched. ## Why Every administrator in Setup saw one page under two names, could not reach SMS Delivery or Data Lifecycle from the sidebar, and read raw codes on System Overview and Notification Events. ## Verification Measured on `main` `5aee2065` (sidebar vs hub, all four locales): en mail "Email" vs "Mail Delivery"; `sms` and `lifecycle` had no sidebar entry; zh-CN and ja-JP company and mail, and es-ES mail, storage and feature flags, differed from the hub. `severity` options were `{ label: 'info', value: 'info' }`…; `sys_audit_log.action` labels equalled their values. Pins, red first on `main` and green on this head: - `service-settings/src/setup-nav-hub-parity.test.ts`: 6 of 9 red on `main` (non-vacuity, set equality `missing: [sms, lifecycle]`, en, zh-CN, ja-JP, es-ES label drift), 9/9 green. - `platform-objects/src/audit/sys-notification-display-labels.test.ts`: object file restored from `main` → 2 red; restored → green. - `plugin-audit/src/objects/sys-audit-log-action-labels.test.ts`: object file restored from `main` → the label case red, the stored-values case green (the values never moved); restored → green. Suites: `@objectstack/platform-objects` 101 files / 1434 tests, `@objectstack/plugin-audit` 66 files / 1053 tests, `@objectstack/service-settings` 63 files / 1025 tests pass; typecheck of all three passes; `pnpm check:i18n`, `check:i18n-coverage`, `check:i18n-stale-fill` pass. `dispatch-gates --commands` derived 61 families at `f3487c44`: 60 exit 0, `check:dual-build-cjs-loads` NOT MEASURED (exit 3, needs every package's dist); `pnpm lint` exit 0. Skills-docs: none — the docs name these pages as "Setup → Settings → SMS Delivery", which still holds. ## Human Minimum - [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic. - [x] 2. Every name I added uses the casing for its kind. - [x] 3. No formatter ran; `pnpm lint` passes. - [x] 4. One issue, one branch off an up-to-date `main`, one pull request. - [x] 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset. - [x] 6. `packages/spec` touched: not touched. - [x] 7. No hand edits to `content/docs/references/`, `packages/*/CHANGELOG.md` or `content/docs/releases/`. - [x] 8. Title, body and comments are in English. - [x] The *Before Submitting* list in CONTRIBUTING.md is done. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_016WV4cxh364AJYtdpWoPiHV --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent c4390f7 commit 8cb8c7f

17 files changed

Lines changed: 319 additions & 44 deletions
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
'@objectstack/platform-objects': patch
3+
'@objectstack/plugin-audit': patch
4+
---
5+
6+
fix(platform-objects): the Setup sidebar names each settings page the way the settings hub does, and lists every page the hub lists; Notification Events and the audit action read in words
7+
8+
Clause-②: no
9+
Metadata-protocol: none
10+
11+
- **One name per settings page.** The Setup sidebar's Configuration entries now carry the hub card's title in every shipped locale. In English, "Email" becomes "Mail Delivery". In zh-CN, ja-JP and es-ES the mail, company, file storage and feature flags entries take the hub's wording (for example 邮件 becomes 邮件投递, 公司信息 becomes 公司).
12+
- **The same set of pages.** SMS Delivery (`nav_settings_sms`) and Data Lifecycle (`nav_settings_lifecycle`) gain sidebar entries; until now they were reachable only through "All Settings". Both require `manage_platform_settings`, as their settings namespaces do.
13+
- **Notification Events.** Severity options read Info / Warning / Critical, and Source Object is drawn as the object's label (the `object-ref` widget the sharing rules use) instead of its api name. The stored values are unchanged: severity keeps `info` / `warning` / `critical`, and the field still stores the object name.
14+
- **Audit action.** Each `sys_audit_log.action` option carries a label ("Config Change" for `config_change`, "Login Failed" for `login_failed`, …), so the English list, detail and System Overview's "Audit Events by Action" chart no longer show the codes. The stored values are unchanged.

‎packages/cli/test/connect-agent-both-halves-wire.pin.test.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,14 +254,14 @@ describe('#17647 — Connect-an-Agent visibility: BOTH halves, over the wire', (
254254
.toContain('nav_connect_agent');
255255
// The Setup tree the platform admin is served BY THIS COMPOSITION: 9
256256
// authored groups less `group_approvals`, which nothing contributes
257-
// into and the filter collapses, plus the 23 entries
257+
// into and the filter collapses, plus the 25 entries
258258
// `SETUP_NAV_CONTRIBUTIONS` carries, plus the MCP one.
259259
// `nav_settings_branding` is not among them, and not because of a
260260
// tenancy wall (this harness boots none): since #24766 it is
261261
// contributed by `@objectstack/service-settings` together with the
262262
// `branding` namespace, offered only where no organization wall stands,
263263
// and this harness composes platform-objects and the MCP bundle alone.
264-
expect(allowedIds).toHaveLength(32);
264+
expect(allowedIds).toHaveLength(34);
265265
expect(allowedIds).not.toContain('nav_settings_branding');
266266
// The two per-user stores are reached from the User record page, not
267267
// from Setup's menu (#23803).
@@ -284,8 +284,8 @@ describe('#17647 — Connect-an-Agent visibility: BOTH halves, over the wire', (
284284
expect(withAccountHalf.statusCode).toBe(200);
285285
expect(withoutAccountHalf.statusCode).toBe(200);
286286
expect(navIds(withAccountHalf.body?.item)).toEqual(navIds(withoutAccountHalf.body?.item));
287-
// 32: the composition the count in the test above states.
288-
expect(navIds(withAccountHalf.body?.item)).toHaveLength(32);
287+
// 34: the composition the count in the test above states.
288+
expect(navIds(withAccountHalf.body?.item)).toHaveLength(34);
289289

290290
// The mechanism behind the invariance, asserted rather than assumed:
291291
// the bundle aims exactly one contribution at `setup` and one at

‎packages/platform-objects/src/apps/setup-nav.contributions.ts‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,19 @@ export const SETUP_NAV_CONTRIBUTIONS: NavigationContribution[] = [
137137
// with the `branding` namespace, which is offered only where no
138138
// organization wall stands (#24766) — so the entry lives and dies with it.
139139
{ id: 'nav_settings_auth', type: 'url', label: 'Authentication', url: '/apps/setup/system/settings/auth', icon: 'lock-keyhole', requiredPermissions: ['manage_platform_settings'] },
140-
{ id: 'nav_settings_mail', type: 'url', label: 'Email', url: '/apps/setup/system/settings/mail', icon: 'mail', requiredPermissions: ['manage_platform_settings'] },
140+
// Every entry below opening a settings page carries that page's hub
141+
// title, and every hub page has one (#27854): the sidebar and the
142+
// "All Settings" hub are two lists of one set of pages. Pinned against
143+
// the registered manifests and both translation bundles in
144+
// `@objectstack/service-settings` (`setup-nav-hub-parity.test.ts`).
145+
{ id: 'nav_settings_mail', type: 'url', label: 'Mail Delivery', url: '/apps/setup/system/settings/mail', icon: 'mail', requiredPermissions: ['manage_platform_settings'] },
146+
{ id: 'nav_settings_sms', type: 'url', label: 'SMS Delivery', url: '/apps/setup/system/settings/sms', icon: 'message-square', requiredPermissions: ['manage_platform_settings'] },
141147
{ id: 'nav_settings_storage', type: 'url', label: 'File Storage', url: '/apps/setup/system/settings/storage', icon: 'hard-drive', requiredPermissions: ['manage_platform_settings'] },
142148
{ id: 'nav_settings_ai', type: 'url', label: 'AI & Embedder', url: '/apps/setup/system/settings/ai', icon: 'sparkles', requiredPermissions: ['manage_platform_settings'] },
143149
{ id: 'nav_settings_knowledge', type: 'url', label: 'Knowledge', url: '/apps/setup/system/settings/knowledge', icon: 'book-open', requiredPermissions: ['manage_platform_settings'] },
150+
// `lifecycle` is `@objectstack/objectql`'s manifest (ADR-0057), offered
151+
// wherever a settings service is mounted, like the entries above.
152+
{ id: 'nav_settings_lifecycle', type: 'url', label: 'Data Lifecycle', url: '/apps/setup/system/settings/lifecycle', icon: 'timer', requiredPermissions: ['manage_platform_settings'] },
144153
{ id: 'nav_settings_feature_flags', type: 'url', label: 'Feature Flags', url: '/apps/setup/system/settings/feature_flags', icon: 'flag' },
145154
],
146155
},

‎packages/platform-objects/src/apps/translations/en.objects.generated.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2531,9 +2531,9 @@ export const enObjects: NonNullable<TranslationData['objects']> = {
25312531
label: "Severity",
25322532
help: "Severity hint for rendering / filtering",
25332533
options: {
2534-
info: "info",
2535-
warning: "warning",
2536-
critical: "critical"
2534+
info: "Info",
2535+
warning: "Warning",
2536+
critical: "Critical"
25372537
}
25382538
},
25392539
suppressed_channels: {

‎packages/platform-objects/src/apps/translations/en.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,14 @@ export const en: TranslationData = {
126126
nav_settings_localization: { label: 'Localization' },
127127
nav_exchange_rates: { label: 'Exchange Rates' },
128128
nav_settings_company: { label: 'Company' },
129-
nav_settings_mail: { label: 'Email' },
129+
nav_settings_mail: { label: 'Mail Delivery' },
130+
nav_settings_sms: { label: 'SMS Delivery' },
130131
nav_settings_branding: { label: 'Branding' },
131132
nav_settings_auth: { label: 'Authentication' },
132133
nav_settings_storage: { label: 'File Storage' },
133134
nav_settings_ai: { label: 'AI & Embedder' },
134135
nav_settings_knowledge: { label: 'Knowledge' },
136+
nav_settings_lifecycle: { label: 'Data Lifecycle' },
135137
nav_settings_feature_flags: { label: 'Feature Flags' },
136138
// Notifications (contributed by @objectstack/service-messaging)
137139
nav_notification_preferences: { label: 'Notification Preferences' },

‎packages/platform-objects/src/apps/translations/es-ES.source-hashes.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,14 @@ export const esESSourceHashes: Readonly<Record<string, string>> = {
106106
'apps.setup.navigation.nav_settings_hub.label': 'a3ac65c7c7f461bf',
107107
'apps.setup.navigation.nav_settings_localization.label': 'beedfaf00452c829',
108108
'apps.setup.navigation.nav_settings_company.label': '9d7f685e11eaade9',
109-
'apps.setup.navigation.nav_settings_mail.label': '632647764b8dff5d',
109+
'apps.setup.navigation.nav_settings_mail.label': '5d0599600587427d',
110+
'apps.setup.navigation.nav_settings_sms.label': '77a3056d33027ca0',
110111
'apps.setup.navigation.nav_settings_branding.label': 'ec6e391065514b64',
111112
'apps.setup.navigation.nav_settings_auth.label': '5c6d7dbd850ca37c',
112113
'apps.setup.navigation.nav_settings_storage.label': 'a2fb526b03c9a9e5',
113114
'apps.setup.navigation.nav_settings_ai.label': 'a6b41a554173f7ab',
114115
'apps.setup.navigation.nav_settings_knowledge.label': '140348539a50d9d5',
116+
'apps.setup.navigation.nav_settings_lifecycle.label': 'cd9fe9c930afed06',
115117
'apps.setup.navigation.nav_settings_feature_flags.label': '4e7e9e879ea1bcc3',
116118
'apps.setup.navigation.nav_notification_preferences.label': '8869f324c1bd545a',
117119
'apps.setup.navigation.nav_notification_templates.label': '9e270c87ef2578df',

‎packages/platform-objects/src/apps/translations/es-ES.ts‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,15 @@ export const esES: TranslationData = {
8585
nav_settings_localization: { label: 'Localización' },
8686
nav_exchange_rates: { label: 'Tipos de cambio' },
8787
nav_settings_company: { label: 'Empresa' },
88-
nav_settings_mail: { label: 'Correo' },
88+
nav_settings_mail: { label: 'Envío de correo' },
89+
nav_settings_sms: { label: 'Envío de SMS' },
8990
nav_settings_branding: { label: 'Marca' },
9091
nav_settings_auth: { label: 'Autenticación' },
91-
nav_settings_storage: { label: 'Almacenamiento de Archivos' },
92+
nav_settings_storage: { label: 'Almacenamiento de archivos' },
9293
nav_settings_ai: { label: 'IA y Embedder' },
9394
nav_settings_knowledge: { label: 'Conocimiento' },
94-
nav_settings_feature_flags: { label: 'Indicadores de Funcionalidad' },
95+
nav_settings_lifecycle: { label: 'Ciclo de vida de los datos' },
96+
nav_settings_feature_flags: { label: 'Indicadores de función' },
9597
nav_notification_preferences: { label: 'Preferencias de Notificación' },
9698
nav_notification_templates: { label: 'Plantillas de Notificación' },
9799

‎packages/platform-objects/src/apps/translations/ja-JP.source-hashes.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,14 @@ export const jaJPSourceHashes: Readonly<Record<string, string>> = {
106106
'apps.setup.navigation.nav_settings_hub.label': 'a3ac65c7c7f461bf',
107107
'apps.setup.navigation.nav_settings_localization.label': 'beedfaf00452c829',
108108
'apps.setup.navigation.nav_settings_company.label': '9d7f685e11eaade9',
109-
'apps.setup.navigation.nav_settings_mail.label': '632647764b8dff5d',
109+
'apps.setup.navigation.nav_settings_mail.label': '5d0599600587427d',
110+
'apps.setup.navigation.nav_settings_sms.label': '77a3056d33027ca0',
110111
'apps.setup.navigation.nav_settings_branding.label': 'ec6e391065514b64',
111112
'apps.setup.navigation.nav_settings_auth.label': '5c6d7dbd850ca37c',
112113
'apps.setup.navigation.nav_settings_storage.label': 'a2fb526b03c9a9e5',
113114
'apps.setup.navigation.nav_settings_ai.label': 'a6b41a554173f7ab',
114115
'apps.setup.navigation.nav_settings_knowledge.label': '140348539a50d9d5',
116+
'apps.setup.navigation.nav_settings_lifecycle.label': 'cd9fe9c930afed06',
115117
'apps.setup.navigation.nav_settings_feature_flags.label': '4e7e9e879ea1bcc3',
116118
'apps.setup.navigation.nav_notification_preferences.label': '8869f324c1bd545a',
117119
'apps.setup.navigation.nav_notification_templates.label': '9e270c87ef2578df',

‎packages/platform-objects/src/apps/translations/ja-JP.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,15 @@ export const jaJP: TranslationData = {
8484
nav_settings_hub: { label: 'すべての設定' },
8585
nav_settings_localization: { label: 'ローカリゼーション' },
8686
nav_exchange_rates: { label: '為替レート' },
87-
nav_settings_company: { label: '会社情報' },
88-
nav_settings_mail: { label: 'メール' },
87+
nav_settings_company: { label: '会社' },
88+
nav_settings_mail: { label: 'メール配信' },
89+
nav_settings_sms: { label: 'SMS 配信' },
8990
nav_settings_branding: { label: 'ブランディング' },
9091
nav_settings_auth: { label: '認証' },
9192
nav_settings_storage: { label: 'ファイルストレージ' },
9293
nav_settings_ai: { label: 'AI と Embedder' },
9394
nav_settings_knowledge: { label: 'ナレッジ' },
95+
nav_settings_lifecycle: { label: 'データライフサイクル' },
9496
nav_settings_feature_flags: { label: '機能フラグ' },
9597
nav_notification_preferences: { label: '通知設定' },
9698
nav_notification_templates: { label: '通知テンプレート' },

‎packages/platform-objects/src/apps/translations/zh-CN.source-hashes.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,14 @@ export const zhCNSourceHashes: Readonly<Record<string, string>> = {
106106
'apps.setup.navigation.nav_settings_hub.label': 'a3ac65c7c7f461bf',
107107
'apps.setup.navigation.nav_settings_localization.label': 'beedfaf00452c829',
108108
'apps.setup.navigation.nav_settings_company.label': '9d7f685e11eaade9',
109-
'apps.setup.navigation.nav_settings_mail.label': '632647764b8dff5d',
109+
'apps.setup.navigation.nav_settings_mail.label': '5d0599600587427d',
110+
'apps.setup.navigation.nav_settings_sms.label': '77a3056d33027ca0',
110111
'apps.setup.navigation.nav_settings_branding.label': 'ec6e391065514b64',
111112
'apps.setup.navigation.nav_settings_auth.label': '5c6d7dbd850ca37c',
112113
'apps.setup.navigation.nav_settings_storage.label': 'a2fb526b03c9a9e5',
113114
'apps.setup.navigation.nav_settings_ai.label': 'a6b41a554173f7ab',
114115
'apps.setup.navigation.nav_settings_knowledge.label': '140348539a50d9d5',
116+
'apps.setup.navigation.nav_settings_lifecycle.label': 'cd9fe9c930afed06',
115117
'apps.setup.navigation.nav_settings_feature_flags.label': '4e7e9e879ea1bcc3',
116118
'apps.setup.navigation.nav_notification_preferences.label': '8869f324c1bd545a',
117119
'apps.setup.navigation.nav_notification_templates.label': '9e270c87ef2578df',

0 commit comments

Comments
 (0)