Skip to content

Commit 98632c1

Browse files
authored
Merge branch 'main' into claude/issue-6084-break-glass-fourth-path
2 parents 65fe2c9 + cba7454 commit 98632c1

67 files changed

Lines changed: 3977 additions & 408 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.

.changeset/console-f995a452d2ca.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
---
2+
"@objectstack/console": minor
3+
---
4+
5+
Console (objectui) refreshed to `f995a452d2ca`. Frontend changes in this range:
6+
7+
Derived from the changesets objectui declared over the range — 64 releasing of 65 changesets added across 98 non-merge commits; omitted: 1 release-nothing changeset, 33 commits carrying no changeset (they ship no package code).
8+
9+
- **minor** — The record detail page now shows a read-gated approval panel (#3461). A record in approval used to expose NOTHING about the running approval to anyone but the current pending appr… (objectui `5af285210`)
10+
- **minor**`DrillDownConfig` now declares only keys a renderer reads, and `target: 'navigate'` is honoured on charts too (#3354). (objectui `9e9e9a92f`)
11+
- **minor** — Console chrome i18n gaps (objectstack#5407). (objectui `3889ffb4c`)
12+
- **minor** — The console language choice now survives a reload. `I18nProvider` writes every language change to `localStorage` (`objectui-locale`, exported as `LOCALE_STORAGE_KEY`) and boots th… (objectui `0554e889c`)
13+
- **minor**`<ObjectChart>` declares `drillDown` as a registry input, so the SDUI save gate treats the segment drill as a contract prop instead of an unknown one (framework#5022). (objectui `524a6357b`)
14+
- **minor** — The environment entitlement dialog now reads its context from `error.details.*` — the single declared location — and the flat dual-dialect tolerance is deleted (objectui#3329, the… (objectui `8ec406728`)
15+
- **minor**`@object-ui/core` now ships the server-action dispatcher factory — `createServerActionHandler({ fetch, baseUrl, resolveObject, ... })` — so any consumer of the runner (standalone… (objectui `5781fb15a`)
16+
- **minor**`AppSchemaRenderer` now derives area visibility from the items inside the area, closing the visible-but-empty regression the spec 17.0.0 area-key retirement left behind (objectui#… (objectui `608669eb5`)
17+
- **minor** — Track `@objectstack/spec` 17.0.0-rc.2 (objectui#3235, #3208, #3287, #3264). (objectui `d22ae31ce`)
18+
- **minor** — Field widgets no longer spread renderer-only props — or arbitrary keys from a field config — onto the DOM element they render (objectui#3291). (objectui `19b8c9be3`)
19+
- **minor**`RichTextField` honours `mobile_fullscreen`, so `mobile.fullscreenLongText` is finally true of rich text too (objectui#3301). (objectui `30ae33a77`)
20+
- **minor**`mobile.fullscreenLongText` finally reaches auto-generated long-text fields, and `mobile_fullscreen` gets one declared carrier (objectui#3245). (objectui `f44d8727f`)
21+
- **minor** — The flow designer writes node geometry as the spec's `FlowNode.position`, not its own `ui: { x, y }` (objectui#3172). (objectui `6e794a19e`)
22+
- **minor****BREAKING (v17)** — field widgets receive their metadata on ONE key, `field`. `schema` is removed from the widget contract (objectui#3233). (objectui `042e09d77`)
23+
- **patch**`UserFilters` no longer carries its own operator table when it lowers a `ViewTab.filter` preset into an ObjectQL AST node. The private `specOperatorToAst` was the second hand-kept… (objectui `d7f350a89`)
24+
- **patch** — Name `CommentThread`'s three emoji-only buttons, and follow the session language past the 7-day mark (objectui#3441) (objectui `65516ba4a`)
25+
- **patch**`toFilterNode` now lowers a spec `ViewFilterRule[]` into ObjectQL AST nodes instead of returning the array verbatim, so a saved view's stored filter reaches `$filter` as something… (objectui `2a9513d81`)
26+
- **patch** — Localize the create / edit / view form title `ObjectView` builds itself (objectui#3462) (objectui `28b2e6571`)
27+
- **patch** — Localize the record-detail headings that `ObjectKanban`, `ObjectTree` and `ObjectView` build themselves (objectui#3459) (objectui `aa36e6073`)
28+
- **patch** — Localize the record-detail overlay heading that `ListView` and `ObjectGrid` build themselves (objectui#3426) (objectui `61958416e`)
29+
- **patch** — The close button that the `Sheet` and `Dialog` primitives auto-render now announces itself in the session locale instead of always in English. Both buttons are icon-only (a lucide… (objectui `71be40696`)
30+
- **patch** — Localize `PresenceAvatars` — the avatar stack's accessible name and tooltips follow the session language (objectui#3440) (objectui `ca0fa8fab`)
31+
- **patch**`PageRenderer` no longer renders its own `<h1>` when the page authors a titled `page:header`, so a page has exactly one level-1 heading. Every non-record page used to render the p… (objectui `06632e9d1`)
32+
- **patch** — Localize `@object-ui/collaboration``CommentThread` no longer hardcodes English (objectstack#5506) (objectui `94c5b7c4e`)
33+
- **patch**`TextAreaField`'s fullscreen edit dialog now gives screen reader users the character count it has always shown sighted ones. The dialog's footer counter was a bare `{n}/{max}` spa… (objectui `f789c3b3a`)
34+
- **patch**`ObjectDataPage`'s "Save as view" now folds the active URL drill conditions into `@objectstack/spec` `ViewFilterRule`s before persisting them, instead of writing the runtime filte… (objectui `875c5fafb`)
35+
- **patch** — Localize `RecordDetailDrawer`'s drag-resize handle (objectstack#5733) (objectui `5a24ad9cb`)
36+
- **patch** — The record picker's filter panel now sends the AUTHORED value of a picked `select` filter option instead of the control's stringified form. Radix `Select` speaks strings — options… (objectui `34d9169f6`)
37+
- **patch** — Localize the record-overlay and tab-badge chrome that #5430's sweep left behind (objectstack#5506) (objectui `5dd012776`)
38+
- **patch** — The lookup "Browse all records" Record Picker's filter panel now offers the options a `select` field declares in its schema (objectui#3336). `LookupField` turns each typed picker… (objectui `5881a2cc4`)
39+
- **patch**`TextAreaField`'s character counter no longer re-announces itself on every keystroke. Measured on `main` in a zh session with `maxLength: 500`, typing a 52-character sentence one… (objectui `789fe3ee2`)
40+
- **patch** — Fix matrix report cells showing another bucket's numbers when dimension values run together. (objectui `509104a1b`)
41+
- **patch** — Fix dataset pivot cells showing another row's numbers when a dimension value contains a space. (objectui `ce7cbe5af`)
42+
- **patch** — Give `InlineCreateRelated`'s card-header close button an accessible name (objectui#3411 — the neighbouring defect found while implementing #3381/PR #3410, in the same file and lef… (objectui `58a00f0b4`)
43+
- **patch** — Give `InlineCreateRelated`'s "Link Existing" search box a real accessible name (objectui#3381 — the neighbouring defect found while implementing #3341/PR #3380, and left out of th… (objectui `b17ce4c25`)
44+
- **patch**`TextAreaField`'s character counter now announces itself in the session locale. The counter block — rendered only when the field declares `maxLength` — carried the accessible name… (objectui `2409e1d04`)
45+
- **patch** — fix(fields): translate the registered path's fullscreen long-text dialog (objectui#3404) (objectui `6fe485bf2`)
46+
- **patch**`TextAreaField` / `RichTextField` now honour `disabled` on their fullscreen editing path. `disabled` used to reach the inline control only: `showFullscreenButton` never consulted… (objectui `7d08c3feb`)
47+
- **patch** — The form renderer's built-in `textarea` branch now honours `readonly` / `disabled` on its fullscreen exit, which previously bypassed both (objectui#3400). `renderFieldComponent` d… (objectui `fd54c3e7a`)
48+
- **patch** — 表单内置 `textarea` 的全屏编辑对话框现在能拿到字段自己的 label:对话框标题显示字段名而不是恒定的通用词「编辑文本」,同一张表单上多个长文本字段的展开按钮也终于有了互不相同的无障碍名(objectui#3393)。 (objectui `85c4c9ce0`)
49+
- **patch** — The form renderer's built-in `textarea` branch reads the fullscreen long-text flag on one spelling (objectui#3303). (objectui `9cbcbf478`)
50+
- **patch** — The form renderer's last user-visible English literals now go through i18n (#3272). The fullscreen long-text editor (`mobile_fullscreen`) was an entire untranslated dialog — title… (objectui `4eeb932aa`)
51+
- **patch** — Localize the last untranslated console-chrome accessible names (objectstack#5430) (objectui `b71fc92f3`)
52+
- **patch**`ObjectGantt`'s quick-filter bar is now localized instead of pinned to Chinese. The four `QuickFilterBar` labels (`all`, `clear`, `empty`, `resultSummary`) were hardcoded as Chine… (objectui `5c856ecb5`)
53+
- **patch** — Associate the label with its control at the two form surfaces where the two were never programmatically connected (objectui#3341 — found while implementing #3299/PR #3340, and del… (objectui `53811d179`)
54+
- **patch**`ActionEngine.getActionsForLocation` now evaluates a `{ dialect: 'cel', source }` action `visible` predicate on the canonical `@objectstack/formula` engine instead of the legacy J… (objectui `18cd43289`)
55+
- **patch** — Settings pages read the declared `{ success, data }` response envelope, so the whole Setup → Configuration section works again against a framework#3843 server (objectui#3366). (objectui `7d0c6de39`)
56+
- **patch** — The flow designer no longer seeds new `wait` nodes with the retired `waitEventConfig.onTimeout` (objectui#3316). (objectui `35da149c5`)
57+
- **patch** — Gallery covers now resolve the `coverField` value through its **file value shape** instead of assuming the field value *is* a URL string, so an ADR-0104-conforming `image` value r… (objectui `978705c8f`)
58+
- **patch** — The list toolbar's "Filter" now saves. Saving a filter from the runtime toolbar PUT the FilterBuilder's whole group object (`{ id, logic, conditions }`) into the view's `filter`,… (objectui `68b6a2855`)
59+
- **patch** — The lookup "Browse all records" Record Picker now formats its columns with the same field metadata the list view uses (objectui#3333). Previously the dialog handed cell renderers… (objectui `9bc3709b9`)
60+
- **patch** — Behavior change — **an authored display `type` can NARROW inline editability, but never WIDEN it** (objectui#3355). (objectui `bbbde1207`)
61+
- **patch**`record:highlights` now honours a `readonly: true` on an authored field entry, so a header chip for a platform-owned column no longer offers inline edit. `HeaderHighlight`'s edita… (objectui `23018cc03`)
62+
- **patch** — Deliver the required state to the control in the five renderers outside the object form that still painted it as an asterisk only (objectui#3299 — the same defect #3290/#3298 fixe… (objectui `532cf8b9e`)
63+
- **patch** — The Combobox trigger now declares `type="button"` explicitly, so it can never submit an enclosing `<form>` (objectui#3344). The current Radix `PopoverTrigger` happens to supply `t… (objectui `34595eb45`)
64+
- **patch**`TagsField` no longer ships a hardcoded Chinese input placeholder (objectui#3342, AGENTS.md Commandment #-1). The placeholder now resolves through the pinned chain: the author-dec… (objectui `c7ed4c366`)
65+
- **patch** — AddressField / GeolocationField sub-inputs now derive their DOM ids from a `useId()` prefix + sub-field name (the RadioField / CheckboxesField `groupId` paradigm) instead of hardc… (objectui `b7165ce47`)
66+
- **patch** — 20 more registered field widgets now announce a failed validation to assistive tech: `multiselect`, `radio`, `checkboxes`, `tags`, `lookup`, `master_detail`, `user`, `owner`, `fil… (objectui `8d8094a7c`)
67+
- **patch**`field:permission-facet-link` now registers through `withFieldCarrier` — the repo's only raw `field:` registration bypassed the single-metadata-carrier seam (objectui#3233), so un… (objectui `c7fba276e`)
68+
- **patch** — The console server-action wrapper's `opensInNewTab` choreography no longer ships hard-coded bilingual Chinese/English copy (objectui#3321, AGENTS.md Commandment #-1): the pre-open… (objectui `a41568462`)
69+
- **patch**`AppSidebar` and `UnifiedSidebar` area switchers now adopt the derived area visibility introduced for `AppSchemaRenderer` in objectui#3311, closing the same visible-but-empty gap… (objectui `8d9984c2e`)
70+
- **patch** — RecordDetailView's `type:'modal'` dispatch no longer falls back to the server-side action handler when the target resolves to neither a page nor an object. That fallthrough could… (objectui `94755bb88`)
71+
- **patch**`field:select` now announces its validation state to assistive tech: the widget's DOM pass-through lands on the Radix `SelectTrigger` — the focusable `<button role="combobox">` a… (objectui `49f7449f9`)
72+
- **patch** — The required state now reaches the input control as `aria-required`, instead of existing only as part of the control's accessible name (objectui#3290). (objectui `680080ada`)
73+
74+
objectui range: `f5bc4c78be76...f995a452d2ca`
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
fix(spec): the reference generator prints a `retiredKey()` tombstone as `never`, not `any` (#5606)
6+
7+
`retiredKey()` is `z.never()`, which `z.toJSONSchema` emits as `{ "not": {} }`
8+
a node with no `type`, no `$ref` and no `enum`. `formatType()` had no branch for
9+
it, so every one of the ~28 tombstones in the spec fell through to the
10+
`prop.type || 'any'` tail and the generated reference pages typed a **removed**
11+
key as **`any`**.
12+
13+
That is the worst available rendering for a retirement. These pages are the
14+
primary input for an upgrading author — very often an AI one (ADR-0033) — and
15+
`heading?: any` does not read "this key was deleted", it reads "this slot exists
16+
and nothing validates it": strictly *more* inviting than the `heading?: string`
17+
it replaced. The author writes it, the parse rejects it with the `[REMOVED]`
18+
prescription, and the prescription arrives only after a wrong metadata file
19+
already exists.
20+
21+
Two changes, both in `scripts/lib/format-type.ts`:
22+
23+
- **`{ not: {} }` now renders as `never`.** Accurate TypeScript — the key's
24+
`z.input` type *is* `never` — and, unlike `any`, self-evident with no prose
25+
to lean on.
26+
- **Tombstones are dropped from an inline shape summary before
27+
`INLINE_KEY_LIMIT` counts.** A summary cell prints `k?: type` for the first
28+
four declared keys and has no description column, so a nested tombstone had
29+
nowhere to put its prescription at all: `ui/theme.mdx` advertised
30+
`{ base?: string; heading?: any; mono?: any }` with both prescriptions
31+
appearing NOWHERE on the page. Retired keys are no longer authorable surface,
32+
so they no longer spend one of the four slots — nor push a key the author
33+
must write behind the ``. The known workaround of moving a tombstone to the
34+
bottom of the shape cannot cover this: #5248 retired `IndexSchema` down to
35+
three live keys, and with a limit of four the first tombstone is then
36+
*mathematically* guaranteed into the summary.
37+
38+
Per-key table rows are unaffected and keep carrying the full `[REMOVED]`
39+
prescription in their description column; their type cell simply now says
40+
`never` instead of `any`.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
'@objectstack/metadata': patch
3+
'@objectstack/metadata-protocol': patch
4+
'@objectstack/objectql': patch
5+
'@objectstack/spec': patch
6+
---
7+
8+
metadata: `getDiagnosed` — a metadata read that FAILED stops arriving as "nobody declared this"
9+
10+
`MetadataManager.loadDiagnosed` computes the ADR-0110 D3 verdict (a MISS and an OUTAGE
11+
are different facts with opposite security meanings) and `get()` discarded it two hops
12+
later: `load()` kept only `.data`, `get()` turned that `null` into `undefined`. Every
13+
consumer of `get()` therefore received one `undefined` for two opposite facts and could
14+
not have told them apart even if it had wanted to.
15+
16+
**New read.** `MetadataManager.getDiagnosed(type, name)` returns
17+
`{ data, degraded, errors }` — the registry-first counterpart of `loadDiagnosed`, declared
18+
as an optional member of `IMetadataService`. A registry hit is never degraded (it
19+
consulted no loader); a clean miss is never degraded (every loader answered).
20+
21+
**`get()` is unchanged — zero breaking.** Same signature, same answer, same behaviour for
22+
every existing caller, including the microtask-level ordering `register()`'s watchers
23+
depend on. Only callers that ASK for the verdict pay for it. Making `get()` throw on
24+
`degraded` was deliberately not done: the boot path degrades on purpose.
25+
26+
**Consumers switched**, each with a disposition argued for its own context rather than one
27+
blanket rule:
28+
29+
- `getMetaItem` / `getMetaItemCached` — a degraded MetadataService read with nothing in
30+
the registry now raises `503 SERVICE_UNAVAILABLE` instead of falling through to
31+
`404 RESOURCE_NOT_FOUND`. This is the half that made the existing `#5532` comment ("
32+
reaching here now means a real miss") untrue.
33+
- `getMetaItemLayered` — the `code` layer joins the rule its `overlay` layer already
34+
followed. `code: null` is a positive claim, and `lockSource = code ?? overlay ?? {}`
35+
derives from it, so an outage could render an item the packager locked
36+
(`_lock: 'full'`) as `editable: true, deletable: true`.
37+
- `ObjectQLPlugin`'s `object` metadata-event refresh — logs `warn` naming the consequence
38+
(the registry keeps the previous definition; nothing retries) and the fix, instead of
39+
`debug` "metadata service has no fresh body". `warn` and not `error` because the write
40+
already landed; only a re-read failed.
41+
42+
Hosts whose `metadata` slot is a shim that predates `getDiagnosed` are read as
43+
"not degraded" — exactly what they could express before — so their behaviour is unchanged.

0 commit comments

Comments
 (0)