Skip to content

Commit 307e5c9

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/project-thread-ybjm3h
2 parents 752f03c + 6817bf1 commit 307e5c9

151 files changed

Lines changed: 2987 additions & 4811 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: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
'@object-ui/plugin-calendar': patch
3+
'@object-ui/plugin-gantt': patch
4+
'@objectstack/spec': patch
5+
'@object-ui/types': patch
6+
'@object-ui/plugin-list': patch
7+
'@object-ui/plugin-view': patch
8+
---
9+
10+
refactor(plugin-calendar,plugin-gantt)!: the calendar and gantt renderers read their binding from the `calendar` / `gantt` block only; the flat fallback read is retired (#25923)
11+
12+
Clause-②: no (narrowing)
13+
Metadata-protocol: none
14+
15+
<!-- adr-0087: not-required (no-migration-prescription) No `@objectstack/spec` key, accepted value, stored row or stored shape moves. The spec's `ComponentPropsMap['object-calendar']` and `['object-gantt']` rows already refuse every flat key this change stops reading, `@object-ui/types` stopped declaring them in the earlier slice of #25923, and both producers in the console (`ListView` and `ObjectView`) already write the block, so no metadata the spec accepts reaches the retired read. A stored-row census over every metadata source this repository reaches (examples, apps, the console's shipped metadata, seeds, fixtures, platform-objects) found no stored view or node that writes the binding flat, so `objectstack migrate meta` has nothing to rewrite. What narrows is the drawing outcome for a host that mounts `ObjectCalendar` or `ObjectGantt` directly with a flat node: it now reaches the refusal screen. The `@objectstack/spec` half is prose only: the two refusals no longer say the renderer still reads the flat spelling. The other categories are closed on facts: the packages publish (not unpublished); no ADR-0087 id covers this change (not registered or already-registered); the narrowed type members are package-local hand-off types that neither package's entry exports (not type-surface-only or runtime-export-retired). -->
16+
17+
`ObjectCalendar` and `ObjectGantt` kept a second, flat reading of their field binding for a host that mounts them directly with the keys written on the node. The spec refuses those keys on the node, `@object-ui/types` no longer declares them, and no producer writes them, so that read was a second dialect nothing should reach. It is retired.
18+
19+
- **`@object-ui/plugin-calendar`**: `getCalendarConfig` reads the `calendar` block only. A node that writes `startDateField`, `endDateField`, `titleField`, `colorField` or `allDayField` flat, with no block, shows the "Calendar configuration required" screen, whose hint names the `calendar` block. The package-local `ObjectCalendarFlatFields` and `ObjectCalendarHandoff` types are gone, and `ObjectCalendarProps['schema']` is the published `ObjectCalendarSchema`.
20+
- **`@object-ui/plugin-gantt`**: `getGanttConfig` reads the `gantt` block only. A node that writes its `GanttConfig` keys flat, with no block, shows the "Gantt configuration required" screen, which now names the `gantt` block, and in development a warning names every flat key the chart did not read, with or without a block beside it. The legacy singular `dependencyField` is read nowhere (the spec spells it `dependenciesField`, inside the block). The package-local `ObjectGanttFlatFields` type is gone; `ObjectGanttProps['schema']` keeps the two search keys `ListView` writes at runtime, now on `ObjectGanttSearchFields`.
21+
- **`@objectstack/spec`**: the `object-calendar` and `object-gantt` flat-key refusals no longer say the renderer still reads the flat spelling. The prescription is unchanged: write the keys in the `calendar` / `gantt` block.
22+
23+
**Supersedes, in the same release:** `25923-calendar-gantt-flat-keys-handoff.md` (the earlier slice of #25923) says the calendar and gantt renderers are unchanged and still read the flat spelling a host hands them, that `ObjectCalendarProps['schema']` and `ObjectGanttProps['schema']` carry the flat keys, and that the spec refusals call the flat spelling a fallback the renderer still reads. This change retires that read, so those sentences no longer hold: the renderers read the block only, the props types carry no flat binding key, and the refusals no longer say it.
24+
25+
**BREAKING** for code that mounts `<ObjectCalendar>` or `<ObjectGantt>` with a flat node.
26+
27+
- **Before.** `<ObjectGantt schema={{ type: 'object-gantt', objectName: 'task', startDateField: 's', endDateField: 'e' }} />` drew a chart, and the flat keys compiled against `ObjectGanttProps['schema']`.
28+
- **Now.** The flat keys are a compile error on the props type, and the node shows the configuration-required screen.
29+
- **Fix.** Write the binding in the block: `{ type: 'object-gantt', objectName: 'task', gantt: { startDateField: 's', endDateField: 'e', titleField: 'name' } }` (the `gantt` block requires `titleField`; the flat branch used to floor it at `'name'`), and `{ type: 'object-calendar', calendar: { startDateField: 'start' } }` for a calendar.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
docs(spec): the `TranslationDataSchema` TSDoc counts sixteen per-app translation groups, not fifteen
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
The comment on `TranslationDataSchema` said "Fifteen groups" after the `hooks` and `books` groups both landed; the per-app bundle (`appTranslationDataShape()`) has sixteen. Comment only: no schema, describe, refusal message or generated artifact changes.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/client': minor
3+
---
4+
5+
feat(client): `data.fieldAccess(object, id)` reads the field projection of one record
6+
7+
Clause-②: yes (widening)
8+
Metadata-protocol: added
9+
10+
`client.data.fieldAccess(object, id)` calls `GET /data/:object/:id/field-access` and resolves to `GetRecordFieldAccessResponse`: the fields the caller may read, and the fields the write gate admits on an update of that stored row. A field permission whose `when` names only some rows is unlocked on the rows it does not name. A row that is absent or unreadable rejects with the record read's 404.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/rest': minor
3+
---
4+
5+
feat(rest): `GET /data/:object/:id/field-access` serves the field projection of one record
6+
7+
Clause-②: yes (widening)
8+
Metadata-protocol: added
9+
10+
A record's edit form can ask which fields it may write on THAT record: the route answers `{ success: true, data: { object, recordId, readable, editable } }` (`GetRecordFieldAccessResponseSchema`), with `editable` judged on the stored row by the write gate through the security service's `getRecordFieldAccess`. The record is read first exactly as `GET /data/:object/:id` reads it, so an absent row or one the caller cannot read answers that route's 404 and the projection discloses nothing more. The route takes no query parameter (a located 400 names any). Without a security service that offers the method it answers 501, and `/auth/me/permissions` remains the row-less reader.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/plugin-security': minor
3+
---
4+
5+
feat(plugin-security): `getRecordFieldAccess` — a record's field projection from the write gate's own verdict
6+
7+
Clause-②: yes (widening)
8+
Metadata-protocol: added
9+
10+
The `security` service answers `getRecordFieldAccess(object, recordId, context)`. It reads the row as the caller reads it (the reader the write gate's pre-image comes from) and asks the field-level write gate itself, `computeForbiddenFieldWrites`, for an update of that row naming every field, over the same permission sets, posture and delegator intersection the gate takes. A field permission whose `when` names only some rows therefore locks the field only on those rows, and the answer cannot disagree with a write of that row. A row that is absent or unreadable answers `null`. `getWritableFields` and every other row-less reader are unchanged and still apply each row-conditioned entry as its lock.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@objectstack/spec': minor
3+
---
4+
5+
feat(spec): a record-scoped field projection, judged on the stored row by the write gate
6+
7+
Clause-②: yes (widening)
8+
Metadata-protocol: added
9+
10+
`GetRecordFieldAccessResponseSchema` (`@objectstack/spec/api`) declares the answer of `GET /api/v1/data/{object}/{id}/field-access`: `{ object, recordId, readable, editable }`, the field projection of ONE record. `ISecurityService` declares its source as the optional `getRecordFieldAccess(object, recordId, context)`: `editable` is the write gate's own verdict on an update of the stored row, so a field permission whose `when` names only some rows locks the field only on those rows, and `readable` is the row-blind read projection. `null` means the caller has no row there (absent or unreadable, deliberately the same answer); `undefined` means no answer.
11+
12+
The `FieldPermissionSchema.when` description now names that reader: the row-less readers (`/auth/me/permissions`, the object-wide field projections, the write preview on an update) keep reporting a row-conditioned entry as its lock, and the record-scoped projection judges it on the row. Nothing an author writes changes meaning.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
fix(spec)!: the engine-side projection declarations (`EngineQueryOptionsSchema.fields`, the RPC request's `select`, the legacy `DataEngineQueryOptionsSchema.select` and the vector-find request's `fields`) declare the projection their transport siblings declare, instead of any list (#26954)
6+
7+
Clause-②: no (narrowing) — the published engine-side declarations of a read's projection (`EngineQueryOptionsSchema.fields`; the deprecated `select` of the RPC query options reached through `DataEngineFindRequestSchema`, `DataEngineFindOneRequestSchema` and `DataEngineRequestSchema`; the deprecated `DataEngineQueryOptionsSchema.select`; and `DataEngineVectorFindRequestSchema.fields`, also an arm of `DataEngineRequestSchema`) refuse a list naming no field, which they admitted before. Nothing is widened and no key is added, removed or renamed.
8+
Metadata-protocol: none
9+
10+
<!-- adr-0087: not-required (no-migration-prescription) No key of any schema is added, removed, renamed or re-shaped and no metadata type or stored shape moves: these are engine and RPC request declarations, never stored, and no metadata type embeds them. A caller names at least one field or leaves the projection out; there is nothing for a migration to rewrite and no tombstone. -->
11+
12+
**BREAKING** accept-set narrowing of published declarations (`@objectstack/spec/data`). No runtime in this repository parses any of these members, so no request served here changes; what can break is code outside it that parses with these exported schemas, or a client generated from their JSON Schema, and sent an empty projection.
13+
14+
- **Before.** `EngineQueryOptionsSchema.fields`, the RPC query's `select`, `DataEngineQueryOptionsSchema.select` and `DataEngineVectorFindRequestSchema.fields` admitted any list of strings: `[]`, and a list with a blank or whitespace-only name.
15+
- **Now.** A list must hold at least one name, and no name may be blank (JSON Schema `minItems: 1`, and a non-blank pattern on each name). All four read this rule from the same declaration as `QueryTransportParamsSchema.select` / `$select` and `GetDataRequestSchema.select`, so the refusal messages are the same.
16+
- **Unchanged.** The inferred types (`string[]`), a named projection, and leaving the projection out. The in-process ObjectQL engine does not parse its options with this schema: `engine.find(object, { fields: [] })` still reads every column, as before.
17+
18+
**The remedy.** Name at least one field, or leave `fields` / `select` out to read every column.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@object-ui/i18n': patch
3+
---
4+
5+
feat(i18n): `chatbot.tool.read_package_doc` and `chatbot.tool.search_package_docs` labels in all ten packs (#27002)
6+
7+
The spec registry `PLATFORM_TOOLS_BY_PACKAGE['service-ai']` now lists the cloud ask agent's two package-doc tools, so the chatbot's tool timeline can show them. Each pack gets a sentence in its own language ("Read the app guide", "Search the app guides" in English; "阅读应用文档", "在应用文档中查找" in Chinese), keeping the `toolLabels-locale-parity-7481` and `toolLabels-sentences-12724` tests green.
8+
9+
Clause-②: no
10+
Metadata-protocol: none
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/spec': minor
3+
---
4+
5+
feat(spec): `PLATFORM_TOOLS_BY_PACKAGE['service-ai']` lists `read_package_doc` and `search_package_docs`
6+
7+
Clause-②: yes (widening)
8+
Metadata-protocol: added
9+
10+
The cloud `ask` agent gains two `service-ai` tools that list and read the installed packages' `doc` items behind the `/meta/doc` audience gate (cloud#3335, the cloud half of #26691). The registry now lists both names, in its alphabetical order, so `PLATFORM_PROVIDED_TOOL_NAMES` carries them: a skill whose `tools[]` names either resolves under ADR-0109 reference integrity instead of being reported as a fictional tool (`ai-skill-tool-unresolved`). That is the whole widening: two more accepted `skill.tools[]` values. No schema shape changes, no export is added or removed, and every other name in the registry stays where it was.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@objectstack/plugin-approvals': patch
3+
---
4+
5+
fix(plugin-approvals): a read of `sys_approval_request` through the generic data door serves the flow and step labels in the reader's language
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
Setup's approval request list, the request's record page, a lookup's title and the export read `sys_approval_request` through the generic data door, which served the stored `process_label` / `current_step_label` to every reader. A zh-CN user saw "Large Deal Approval" / "Sales Manager Review" there while the approvals inbox showed the same rows translated.
11+
12+
- **The same lookup as the approvals door.** The data door now overlays `process_label` and `current_step_label` with the app's language pack entries (`flows.FLOW.label`, `flows.FLOW.approvals.NODE.label`) for the reader's locale (`Accept-Language`, else the workspace `localization` settings), by the same lookup `GET /api/v1/approvals/requests` applies, so both doors serve the same text for the same row.
13+
- **Stored text on a miss.** A label the pack does not carry, a locale no pack holds, a read with no locale and a system read are served the stored text, as before.
14+
- **Same columns.** A read that selects a label without `process_name` / `current_step` is still served only the columns it selected; no column is added (`step_label` and `object_label` stay approvals-door fields).
15+
- **Storage is untouched.** The overlay happens on the rows a read hands back; the stored labels stay the authored text as the request opened with it. Filtering, sorting and grouping on `process_label` / `current_step_label` still compare the stored text.

0 commit comments

Comments
 (0)