Repository navigation
Commit f76c622
fix(platform-objects): Setup → Users opens on the All Users list view (#21971)
Fixes #21960
Clause-②: no
## What changes
Setup → Users now opens on the **All Users** list view (`all_users`).
Before this, it opened **My Profile** (`me`): one row, the
administrator, with a page size of 1.
- `packages/platform-objects/src/apps/setup-nav.contributions.ts`:
`nav_users` gains `viewName: 'all_users'`. That key is the one
`ObjectNavItemSchema` already declares on an object navigation item
("Default list view to open"). No new key.
- `packages/platform-objects/src/identity/sys-user.object.ts`: a comment
only. The `me` view's comment said the Account App surfaces it. At
`main` it does not (see the readers below), and the comment now names
what does reach it.
- `packages/platform-objects/src/apps/setup-users-nav-view.test.ts`: the
pins.
- `.changeset/21960-setup-users-all-users.md`:
`@objectstack/platform-objects` patch.
⛔ No `listViews` reorder, no view removed, no `packages/spec` edit, no
governed surface.
Implemented by the os-dev run of session
`session_017ErfyP2Rx7XWHJA27QjyUi` on branch
`claude/issue-21960-setup-users-all-users`.
## The console honours `viewName` (measured, H1)
Read in objectui at the commit `.objectui-sha` pins,
`0abd4f9f8769fc4c19ad2f96707684876f74c09f`:
- `packages/layout/src/NavigationRenderer.tsx`, `resolveHref`, case
`object`. The precedence is `recordId`, then `filters`, then `viewName`.
With `viewName` the href is `OBJECT/view/VIEWNAME`; without it, the bare
`OBJECT` path.
- `packages/app-shell/src/views/ObjectView.tsx`. The active view is the
URL view id, then `?view=`, then a view marked `isDefault`, then
`views[0]`. Only the object's primary `list` is marked `isDefault`
(`buildViewTabs`), and `sys_user` declares none, so `views[0]` is the
first declared list view: `me`. That is what the card observed.
- `packages/core/src/utils/resolve-view-id.ts` matches the short name
`all_users` against the qualified id `sys_user.all_users`.
- "Defaults to "all"" in the spec's `viewName` describe does not hold
for an object that declares list views. `all` is only the id of the
fallback tab the console builds for an object with no list views. This
is reported on the card; it is not edited here, because it is spec text.
The served path keeps the key as authored. `applyNavContributions`
(`packages/objectql/src/registry.ts`) pushes contributed items into a
structured clone of the app, and `filterNav`
(`packages/rest/src/meta-item-read-gate.ts`) pushes a passing leaf item
unchanged. `nav_notifications` already ships `viewName: 'recent'`
through the same contribution path.
## Who reads `me` (measured, H2)
- **Navigation items: none.** The Account app's profile entry is
`nav_account_profile`: `type: 'component'`, `componentRef:
'account:profile_card'`. No Account entry routes to `sys_user`.
- **objectui at the pin: none by name.** `account:profile_card` is
registered in `apps/console/src/registerAccountComponents.tsx` and
renders `ProfilePage`, which reads the signed-in user from `useAuth()`
and writes through `updateUser`.
- **Pages: none.** `pages/sys-user.page.ts` names no list view.
- **Tests: none.**
- **Other references:** the four generated translation bundles carry the
tab's label, and the spec's `ObjectNavItemSchema` docblock cites
`sys_user.me` as an example of the `{current_user_id}` filter
vocabulary.
So `me` is reached only as a tab, and as the default tab when a route
names no view. Triage's second pin ("the Account app's My Profile still
opens on the caller's own row") is held by the profile component, and it
is pinned there.
## Pins
`setup-users-nav-view.test.ts`, 7 cases:
- `nav_users` sits in `group_people_org` with `type: 'object'`,
`objectName: 'sys_user'` and `viewName: 'all_users'`;
- it carries neither `recordId` nor `filters`, both of which
`resolveHref` honours ahead of `viewName`;
- `sys_user.listViews.all_users` exists under that same name;
- that view is not scoped to the caller: no `filter`, no
`{current_user_id}` anywhere in it, and a page size above 1;
- the contribution passes a full
`NavigationContributionSchema.safeParse`, and the parsed item keeps
`viewName: 'all_users'`;
- the Account app's first entry is `nav_account_profile`, the
`account:profile_card` component;
- no Account entry routes to `sys_user`.
**No dogfood door pin.** The framework half of the door is the served
Setup nav, and both sites on that path pass the item through as authored
(above). The data half is unchanged by this diff: `all_users` carries no
filter. A door case would assert what the metadata pin already holds.
## Reverse verification
On committed `6639eb4a52`:
```text
node scripts/ablation-replace.mjs --file packages/platform-objects/src/apps/setup-nav.contributions.ts \
--anchor "viewName: 'all_users', " --delete -- \
pnpm --filter @objectstack/platform-objects exec vitest run --maxWorkers=2 src/apps/setup-users-nav-view.test.ts
```
- **Mutation landed:** anchor 1 → 0, blob `72a3adcc1066` →
`7c70ade946a9`.
- **Result: 4 failed | 3 passed (7).** The four cases that read
`nav_users.viewName` went red. The `recordId` / `filters` case and both
Account cases stayed green, as expected, because none of them reads
`viewName`.
- **Restored:** the blob after restore, `72a3adcc1066`, equals the HEAD
blob, and `git diff HEAD` is empty. `git status --porcelain` was empty
afterwards.
- **Resolution path:** the test imports its subject by relative path
from `src/`, not through the package `exports`, so no `dist/` sits
between the mutation and the run.
- **First attempt:** it was refused by the tool before anything ran,
because its replacement text already appeared inside the anchor. It ran
nothing and restored.
## Tests and gates, at `eb9b315b28`
That is the merge of `origin/main` at `2a22177ae7`. `packages/spec` was
rebuilt after the merge, then the whole workspace (`turbo run build
--concurrency=2`, 72 tasks).
- `pnpm --filter @objectstack/platform-objects exec vitest run
--maxWorkers=2`: **Test Files 61 passed (61), Tests 967 passed (967).**
- `pnpm --filter @objectstack/platform-objects typecheck`: **exit 0**,
with `check:test-typecheck: OK`.
- The new test file is in the `tsconfig.test.json` program, counted with
`--listFiles`.
- The three errors that program reports are the ledgered
`feature-gate-guard.test.ts` debt.
- `node scripts/pm/dispatch-gates.mjs --commands` derived **63**
commands, and all 63 exited 0.
- The `--ran` reconciliation reads `63 derived, 63 run, 0 NOT-MEASURED,
0 UNRUN`. That is a derived zero: every line carried its exit code.
- **14 are new against the dispatch-time list:**
`check-adr-0087-registration` (base and self-test),
`check-empty-changeset` (base and self-test), `release-rehearsal-clone
--self-test`, `release-pending-publish --self-test`,
`check:engine-double-contract`, `check:objectql-double-limit`,
`check:objectui-changeset`, `check:pm-changeset-deadline-census`,
`check:query-options-erasure`, `check:type-check-coverage`,
`check:type-check-debt` and `check:where-matcher`.
- **Artifact-roster block** (55 families, all run): 52 exited 0.
- `check-closing-target-claim.mjs`, `check-partof-closing-keyword.mjs`
and `check-single-claim-paths.mjs` answer NOT WIRED without a PR
context. CI runs them with one.
- `check-partof-closing-keyword.mjs` also exits 0 on this body when
`PR_BODY` is set locally. The other two need the PR number.
- **Symbol-anchor sweeps:** `check:adr-symbol-anchors`,
`check:scripts-symbol-anchors`, `check:spec-docblock-symbol-anchors` and
`check:adr-anchors` all exited 0.
- **Prerequisite refusals, then reruns:**
- `check:dual-build-cjs-loads`, `check:i18n`, `check:lean-entry-closure`
and `check:published-readme-exports` first refused with exit 3 (no
`dist/`). After the full build all four exited 0, and `check:i18n` reads
"all bundles in sync".
- `check:type-check-debt` first hit the runner's 420 s cap while it
refreshed its closure. The rerun exited 0, with "1 ledger entr(ies)
re-measured ... none above its recorded number".
- **ESLint, narrowed to the three touched TypeScript files:** 3 files, 0
errors, 0 warnings.
- The population is read from `eslint.config.mjs`: its
`packages/**/*.{ts,tsx,mts,cts}` blocks match all three, and none was
reported as ignored.
- The count comes from `--format json`.
- The config enables no type-aware linting (no `parserOptions.project`),
so this diff cannot move a verdict on an untouched file.
- The repo-wide `pnpm lint` is CI's.
## Acceptance notes
- **Other doors still open on `me`.** objectui's `AppHeader` links the
object breadcrumb segment and the object switcher to the bare object
path, and a bare path opens `views[0]`. So from a user's record page,
the "Users" breadcrumb still lands on My Profile. This PR closes the
Setup nav door, as dispatched. Changing which view `sys_user` opens by
default is the declaration-order route, which the dispatch reserved. It
is reported on the card.
- **Sidebar highlight.** objectui's `resolveActiveNavItem` scores a
`viewName` item only on its own view. So `nav_users` no longer lights up
on a user's record page or on the other tabs, where the bare item used
to claim every `sys_user` sub-route. Every `viewName` entry behaves this
way today (`nav_notifications`, and the Account `mine` entries). This
was read from source at the pin, not measured in a browser.
- **Six other Setup entries land an admin on a caller-scoped first
view.** `nav_api_keys`, `nav_sessions`, `nav_oauth_apps`, `nav_accounts`
and `nav_user_preferences` each open a `mine` view first, and
plugin-sharing's `nav_record_shares` opens `granted_to_me` first. Their
page sizes are 50 to 100, so these are not one-row views. They are
reported on the card, not fixed here.
---
_Generated by [Claude
Code](https://claude.ai/code/session_017ErfyP2Rx7XWHJA27QjyUi)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent 0d8ea5e commit f76c622
4 files changed
Lines changed: 154 additions & 6 deletions
File tree
- .changeset
- packages/platform-objects/src
- apps
- identity
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
68 | 68 | | |
69 | 69 | | |
70 | 70 | | |
71 | | - | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
72 | 78 | | |
73 | 79 | | |
74 | 80 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
601 | 601 | | |
602 | 602 | | |
603 | 603 | | |
604 | | - | |
605 | | - | |
606 | | - | |
607 | | - | |
608 | | - | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
609 | 612 | | |
610 | 613 | | |
611 | 614 | | |
| |||
0 commit comments