Skip to content

Commit 76760f4

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/project-thread-xn40qf
2 parents 06816ae + 6d15aca commit 76760f4

47 files changed

Lines changed: 1191 additions & 1869 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
'@objectstack/core': patch
3+
'@objectstack/mcp': patch
4+
'@objectstack/plugin-audit': patch
5+
'@objectstack/plugin-hono-server': patch
6+
---
7+
8+
refactor(core)!: `resolveLocalizationContext` takes the organization as `organizationId`; the `tenantId` key is retired
9+
10+
Clause-②: no (narrowing)
11+
Metadata-protocol: none
12+
13+
<!-- adr-0087: not-required (runtime-export-retired @objectstack/core#ResolveLocalizationInput.tenantId) the retired member is a key of a published runtime TypeScript input with no Zod schema, no spec declaration and no stored shape; the compiler reports it at every object-literal call that still spells it, and nothing exists for `objectstack migrate meta` to rewrite -->
14+
15+
**BREAKING** for a TypeScript caller of `resolveLocalizationContext` from `@objectstack/core`. The key that names the organization to localize for is renamed. There is no alias and no deprecation window.
16+
17+
`ResolveLocalizationInput.tenantId` always meant the **organization** id: the settings service stores and reads `localization` under the organization (ADR-0131 D8), and the direct `sys_setting` fallback reads that organization's rows. The name did not say so, and an environment id passed there type-checked. It matched no organization's settings, so every non-UTC organization silently resolved its timezone as `UTC`, and the date boundaries cut from it moved with it. The key is now `organizationId`, and the resolver reads no other spelling at run time.
18+
19+
- FROM `ResolveLocalizationInput.tenantId` TO `ResolveLocalizationInput.organizationId`: pass the caller's organization id under the new key, `resolveLocalizationContext({ ql, settings, organizationId, userId })`. Never pass an environment id.
20+
21+
**Who moves.** A caller that builds the input as an object literal with `tenantId` gets a compile error (excess property) and makes the one-key fix above. A caller that builds it some other way, such as spreading an object that holds `tenantId` or passing a variable typed wider than the input, does not get that error: its `tenantId` is ignored and the resolver localizes as for a caller with no organization, so grep for `tenantId` beside `resolveLocalizationContext`. In this repository the four callers (`@objectstack/core`'s request execution context, `@objectstack/mcp`, `@objectstack/plugin-audit` and `@objectstack/plugin-hono-server`) are migrated here and behave as before.
22+
23+
**Not moved.** The settings service's own scope argument, `{ tenantId, userId }` on `get` / `getMany`, keeps its spelling. It is a separate surface with its own callers. The resolver passes the organization id there as before.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@object-ui/layout': patch
3+
---
4+
5+
feat(layout): a collapsed sidebar navigation group shows how many entries it holds
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
- **Before.** A closed navigation group drew its label and a chevron and nothing else, so a closed group holding one entry looked exactly like one holding ten, and users did not open it to find what was inside.
11+
- **Now.** While a group is collapsed, `NavigationRenderer` draws a small count badge between its label and its chevron. The count is what opening the group would reveal: the entries that pass the same per-item guards the renderer applies (the `visible` expression, `requiredPermissions`, the `requiresObject` / `requiresService` capability gates, a `doc` entry's readability check, and an `action` entry only when the host wires `onAction`), counted through nested groups. Separators and the groups themselves are not entries. It is the same walk that decides whether a group renders at all (`hasVisibleNavigationItems`), so the count cannot disagree with the opened group.
12+
- **When it does not show.** An open group shows no count, because its entries are in view. A group that holds the current route is forced open, so it never shows one. In the icon rail the badge is hidden under the same classes as the group label.
13+
- **Accessibility.** The badge is `aria-hidden`: the disclosure's accessible name stays the group label, and the disclosure already announces collapsed or expanded.
14+
15+
What to do: nothing. No navigation key or value changes, and no translation key is added.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
---
4+
5+
fix(app-shell): the Console no longer sends two requests it knows will be refused, the drafts ledger for a member and the published body of a new draft
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
- **Home's drafts row** read `GET /api/v1/meta/_drafts` for whoever opened Home. A member holding none of the capabilities the ledger admits (`studio.access`, `setup.access` or `manage_metadata`) got a 403, and the console logged it as a failed request on every visit. The row now reads the ledger only for a session that holds one of them, through the new `useCanReadPendingDrafts()`. An unreported capability set still reads it, and the server still enforces the gate.
11+
- **The pending-changes sheet** (Studio's Publish and Changes, and the draft-preview bar's Changes) read each draft's published body beside its draft. Under Publish, where every row opens expanded, that read was sent before the sheet knew which drafts are new, so a draft-only object such as one just saved from New object got `GET /api/v1/meta/object/NAME?package=PKG` → 404. A row now waits for its new-or-update classification, and a new draft is not asked for a published body. A row whose classification read failed is read both ways, as before.
12+
13+
What to do: nothing. The pages render exactly as before.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
---
4+
5+
fix(app-shell): the Setup → Positions list shows each position's description
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
The position list in Setup declared only Name, Label, Holders and Permission sets, so a position's `description`, which `GET /meta/position` already serves, was never shown. The list now has a Description column right after Label, the same column the permission-set list next to it has. A position without a description shows the empty cell. The text is the served one, so a description the translation bundle's `positions` namespace translates shows translated, like the label.
11+
12+
What to do: nothing.

0 commit comments

Comments
 (0)