Skip to content

Commit efb181a

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/project-thread-ufaqzz
Brings in #27340 (ObjectFieldInspector, studio i18n) before the PR opens; no conflicts. Claude-Session: https://claude.ai/code/session_01Utp6CbCrKUjGeTReNEmUJx Co-authored-by: Claude <noreply@anthropic.com>
2 parents 73b0ad8 + 1ed3360 commit efb181a

119 files changed

Lines changed: 3236 additions & 171 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: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
'@object-ui/core': patch
3+
'@object-ui/i18n': patch
4+
'@object-ui/fields': patch
5+
'@object-ui/components': patch
6+
'@object-ui/plugin-form': patch
7+
'@object-ui/plugin-grid': patch
8+
'@object-ui/plugin-list': patch
9+
'@object-ui/plugin-dashboard': patch
10+
'@object-ui/plugin-report': patch
11+
'@object-ui/plugin-detail': patch
12+
'@object-ui/plugin-gantt': patch
13+
'@object-ui/app-shell': patch
14+
---
15+
16+
feat(ui): a `record`-mode currency amount shows each record's own currency; the code field is an ISO 4217 select pre-filled with the organization currency; Studio edits the mode and the pointer (ADR-0144 D2, D6, D8 rule 4)
17+
18+
Clause-②: no
19+
Metadata-protocol: none
20+
21+
An amount declaring `currencyConfig: { currencyMode: 'record', currencyField: 'currency_code' }` now renders in the currency its record's `currency_code` holds, on every face that holds the record:
22+
23+
- **Cells and widgets.** `resolveFieldCurrency(field, tenantDefault, record)` takes the record in scope as an optional third argument. Under `record` mode it reads only that record's code field; no record, or a blank code, resolves to no currency, so the amount shows as a plain number and never in the tenant default. `dynamic` and `fixed` fields resolve exactly as before. The list cell, the form and inline amount box (symbol, decimals and spinner step follow the selected code), formula cells returning `currency`, the record page's summary chips, the dashboard table and record drawer, and Gantt tooltips all pass the record. `recordCurrencyField(field)` names the pointer.
24+
- **The code field.** A `text` field declaring `valueDomain: 'iso_4217_currency'` renders a searchable select instead of a free-text box, grouped "Available" (the organization currency, then rated currencies, then the codes the object's records already hold) and "All currencies (ISO 4217)". It offers only codes the value domain accepts. The form reads the used codes once per object, with one grouped query, and hands them to the field on its own metadata (`usedCurrencyCodes`); a data source without grouped queries offers home + the record's own code. The rated group is empty until the exchange-rate table ships. The picker itself is `CurrencyCodePicker` in `@object-ui/components`.
25+
- **Filters.** In the list's filter builder, a condition on a `record`-mode amount gains a required currency picker, defaulting to the organization currency, and the filter reads `amount op X AND code = C`: the code condition is a second row of the same group, so stored filters keep their shape. A group holding such a pair stays on AND (under OR the pair would split), and a stored OR group says so. Presence checks (`is null`, `is empty`, …) need no currency.
26+
- **Create forms.** A code field that a `record`-mode amount points at opens pre-filled with `localization.currency`, as a value the user submits; a declared `defaultValue` and the caller's record win, and nothing is seeded while the setting is unset.
27+
- **Totals.** The grid footer draws no sum, average, minimum or maximum for a `record`-mode amount (its rows are in different currencies); counts stand. A group header keeps those aggregates only when the grid is grouped by the amount's code field. Consolidated totals belong to the home field, a `dynamic` amount that totals as before.
28+
- **Dataset answers.** A grouped analytics answer over a `record`-mode amount marks its measure column with `currencyField`, the result column holding each row's code. The dashboard `table` widget, the report table (and its export) and the Studio dataset preview format each row in that row's currency; a row without a code, and the totals row, show a plain number. `measureCellCurrency(field, row)` in `@object-ui/core` is the one read. Columns without `currencyField` format exactly as before.
29+
- **Studio.** A currency field (or a formula returning `currency`) gains a currency section: the mode (dynamic, fixed, record), the fixed code, and under `record` a `currencyField` picker listing the object's ISO 4217 code fields, with "Create currency field", which adds `currency_code` (`text`, `valueDomain: 'iso_4217_currency'`, required) and points the amount at it.
30+
31+
⛔ Not released alone: this ships in the same release as `currencyMode: 'record'` itself and its aggregate refusals.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@objectstack/types': patch
3+
'@object-ui/console': patch
4+
---
5+
6+
fix(types, console): a shared `record`-mode currency amount shows its record's own currency (ADR-0144 D2, D9)
7+
8+
Clause-②: no
9+
Metadata-protocol: none
10+
11+
The share-link resolve answer's field projection (`buildShareLinkResolveAnswer`, `@objectstack/types`) carried a currency field's `currencyMode` and `defaultCurrency` only, so a shared `record`-mode amount, whose currency lives in a sibling code field, rendered as a plain number. A currency field's projected `currencyConfig` now also carries `currencyField`, the amount's code-field pointer, when the answer's `record` carries that code field. A link that redacts the code field gets neither the code nor the pointer, so the answer still describes nothing the record hides, and the amount shows as a plain number.
12+
13+
The shared-record page hands the shared record to the currency face, which reads the code from it, so the amount shows in the currency its own record names. Every other field and every other key of the answer is unchanged.
14+
15+
⛔ Not released alone: this ships in the same release as `currencyMode: 'record'` itself.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@objectstack/spec': minor
3+
'@objectstack/objectql': minor
4+
---
5+
6+
fix(i18n): a tenant's rewrite of a packaged validation rule message is served as written in every locale, on the refusal and on `/meta` (#27221)
7+
8+
Clause-②: yes (widening)
9+
Metadata-protocol: semantic
10+
11+
A package's bundle translates the rule messages that package shipped (`objects.<object>._validations.<rule>.message`). When a tenant overlaid a packaged object and reworded one of its validation rule messages, keeping the rule's name, a reader in any locale the bundle carries got the package's translation instead of the tenant's sentence. The rejected write's error and the rule served by `/meta` (and the public form) both showed it.
12+
13+
- **Now.** Both readers apply the bundle entry only while the served message still equals the packaged rule's message of the same name. A message that differs is the tenant's own and is served and returned as written, in every locale. Rules the tenant left alone are still translated. A `conditional` branch is matched by its own name. A rule the owning package does not declare (one an `objectExtensions` entry adds, or one the tenant added) has no packaged message to differ from and is still translated under its own name, as before. With no packaged owner (an object authored entirely at runtime), nothing changes.
14+
- **One rule, both readers.** `/meta` (`translateObject`) and the rule evaluator use the same comparison, the one already applied to an object's `label`, `description`, embedded list views and fields. `/meta` and the refusal of the same write still show one sentence for one rule and locale.
15+
- **`scalarOverridesPackagedBase`** (`@objectstack/spec/system`) now also accepts the key `'message'`, so the rule evaluator judges a rule message through it. Its behaviour for the existing keys is unchanged.
16+
- **`evaluateValidationRules`'s `messages` option** (`EvaluateRulesOptions.messages`, `@objectstack/objectql`) gains an optional `packagedRule` lookup, which the engine fills from the object's packaged owner. A caller that passes its own `messages` without it keeps the previous behaviour.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
'@objectstack/skills': patch
3+
'@objectstack/spec': patch
4+
'@objectstack/metadata': patch
5+
'@object-ui/i18n': patch
6+
'@object-ui/plugin-grid': patch
7+
'@object-ui/components': patch
8+
'@object-ui/fields': patch
9+
'@object-ui/types': patch
10+
'@object-ui/plugin-form': patch
11+
'@object-ui/console': patch
12+
---
13+
14+
docs(skills): hand-written inventory counts are deleted; the names and the source of truth stay
15+
16+
Clause-②: no
17+
Metadata-protocol: none
18+
19+
- **Before.** `objectstack-data` counted its field types ("49") in SKILL.md and in `rules/field-types.md`, and its lifecycle events ("8") in SKILL.md and `references/data-hooks.md`; `objectstack-automation` counted its built-in node types ("20"); `objectui/README.md` counted its plugins ("18"); `objectui/guides/schema-expressions.md` counted the formula registry ("30 functions"); `objectstack-query` counted the aggregate functions ("six"). No gate reads any of those numbers against the tree, so each one goes wrong the moment the inventory moves, and a wrong count misleads the reader more than no count.
20+
- **Now.** The numbers are gone; every enumeration that taught something (the node-type tables, the plugin names, the function table, the aggregate names) stays, and each page still points at the file or schema that is the source of truth. Deletion only: every touched file shrinks under its unchanged token ceiling.
21+
- The same deletion in shipped READMEs and one shipped source comment: `@objectstack/spec` (a `//` comment in `src/kernel/metadata-plugin.zod.ts`, which ships), `@objectstack/metadata` (README), and the `@object-ui/*` READMEs of i18n, plugin-grid, components, fields, types, plugin-form and console. No schema, key or behaviour changes.

‎content/docs/api/error-catalog.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ navTitle: Error Code Catalog
44
description: Complete reference for all ObjectStack error codes with causes, fixes, and retry strategies
55
---
66

7-
ObjectStack uses a structured error system with **9 error categories** and **56 error codes reachable on the wire**. Every error includes a machine-readable code, HTTP status mapping, and retry guidance.
7+
ObjectStack uses a structured error system of **error categories** and **56 error codes reachable on the wire**, catalogued in full below (that count is pinned by `packages/spec/src/api/error-catalog-docs.test.ts` against the wire face). Every error includes a machine-readable code, HTTP status mapping, and retry guidance.
88

99
This catalog documents the **wire face** — the codes a client can actually receive. That is not quite the
1010
`StandardErrorCode` enum: the enum also carries in-process spellings the REST door translates at the

‎content/docs/capabilities/analytics.mdx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
---
22
title: Analytics — dashboards, reports and charts
33
navTitle: Analytics & Dashboards
4-
description: ~20 chart families, period-over-period comparison, runtime filters, TV display pages, and four report shapes
4+
description: Chart families, period-over-period comparison, runtime filters, TV display pages, and the report shapes
55
---
66

77

88
The executive cockpit and the ops detail report are both configured, not built. Data is live, and permissions apply inside every chart — each viewer sees only the numbers they are allowed to see.
99

1010
## Dashboards
1111

12-
Compose from roughly twenty chart families:
12+
Compose from the chart families:
1313

1414
- **Single values**: KPI tiles, gauges, progress rings — total pipeline, quarter-to-date closed, target attainment.
1515
- **Comparisons**: bar and column by stage, rep, or product line.
@@ -26,7 +26,7 @@ Dashboard extras that matter in practice:
2626

2727
## Reports
2828

29-
Four shapes — **tabular** (detail rows), **summary** (grouped totals), **matrix** (regions × quarters), and **joined** (several dataset panels) — with runtime filters and export.
29+
The shapes — **tabular** (detail rows), **summary** (grouped totals), **matrix** (regions × quarters), and **joined** (several dataset panels) — with runtime filters and export.
3030

3131
> **In HotCRM**: four dashboards (executive, sales, service, CRM overview) and six reports (lead, opportunity, account, case, churn), fed by six shared datasets covering accounts, contacts, leads, opportunities, products, and cases. The executive dashboard carries quarter and owner filters plus the funnel and trend widgets described above.
3232

‎content/docs/capabilities/approvals.mdx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
---
22
title: Approvals — routing, queues and audit trail
33
navTitle: Approvals
4-
description: Seven ways to pick approvers, four decision modes including group sign-off, record locking, overdue escalation, and send-back-for-revision
4+
description: Ways to pick approvers, decision modes including group sign-off, record locking, overdue escalation, and send-back-for-revision
55
---
66

77

88
Discounts, contracts, spend — anything that needs a human "yes" becomes an approval step in a flow, replacing the group-chat shoulder tap with a tracked, enforceable decision.
99

10-
## Who approves — seven resolution styles
10+
## Who approves — the resolution styles
1111

1212
A specific person · everyone holding a position (e.g. sales managers) · the submitter's direct manager (needs each user's manager set — see below) · a team · a department (optionally including sub-departments) · organization leadership · **a person named on the record itself** (e.g. the "regional director" field).
1313

@@ -23,7 +23,7 @@ request opens and waits for an administrator. The details, and the fallback that
2323
data at all, are in [Automation → Approvals](/docs/automation/approvals).
2424
</Callout>
2525

26-
## How it passes — four decision modes
26+
## How it passes — the decision modes
2727

2828
| Mode | Rule | Fits |
2929
|---|---|---|

‎content/docs/capabilities/automation.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Automation — processes that run themselves
33
navTitle: Automation — Processes That Run Themselves
4-
description: Five trigger styles, visual flow diagrams, notifications, branching, loops, waits, and external calls — the work nobody should have to remember
4+
description: Trigger styles, visual flow diagrams, notifications, branching, loops, waits, and external calls — the work nobody should have to remember
55
---
66

77

‎content/docs/capabilities/data.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Business data — objects, fields and records
33
navTitle: Manage Business Data
4-
description: Objects, 40+ field types, auto-computed fields, and relationships — every spreadsheet you run the business on, structured and governed
4+
description: Objects, field types, auto-computed fields, and relationships — every spreadsheet you run the business on, structured and governed
55
---
66

77

‎content/docs/capabilities/index.mdx‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ If you are a developer, the [Build sections](/docs/data-modeling) cover the same
1212
## The capabilities
1313

1414
<Cards>
15-
<Card href="/docs/capabilities/data" title="Manage Business Data" description="Objects, 40+ field types, formula and roll-up fields, relationships from lookups to hierarchies" />
16-
<Card href="/docs/capabilities/views" title="Views — See Data Your Way" description="Nine lenses over the same records: table, kanban, calendar, gantt, map and more — plus saved filters and global search" />
15+
<Card href="/docs/capabilities/data" title="Manage Business Data" description="Objects, field types, formula and roll-up fields, relationships from lookups to hierarchies" />
16+
<Card href="/docs/capabilities/views" title="Views — See Data Your Way" description="Many lenses over the same records: table, kanban, calendar, gantt, map and more — plus saved filters and global search" />
1717
<Card href="/docs/capabilities/forms" title="Forms & Data Quality" description="Wizards, conditional fields, validation on save, legal stage transitions, public web-to-lead forms" />
18-
<Card href="/docs/capabilities/automation" title="Automation" description="Five trigger styles and visual flows: reminders, hand-offs, escalations, and scheduled work that runs itself" />
19-
<Card href="/docs/capabilities/approvals" title="Approvals" description="Seven approver styles, four decision modes including group sign-off, locking, SLA escalation, send-back" />
20-
<Card href="/docs/capabilities/permissions" title="Permissions — Who Sees What" description="Four layers from object capability to per-field visibility, five data-depth scopes, audit, and an explain API" />
21-
<Card href="/docs/capabilities/analytics" title="Analytics & Dashboards" description="~20 chart families, period-over-period, runtime filters, TV display pages and reports" />
18+
<Card href="/docs/capabilities/automation" title="Automation" description="Trigger styles and visual flows: reminders, hand-offs, escalations, and scheduled work that runs itself" />
19+
<Card href="/docs/capabilities/approvals" title="Approvals" description="Approver styles and decision modes including group sign-off, locking, SLA escalation, send-back" />
20+
<Card href="/docs/capabilities/permissions" title="Permissions — Who Sees What" description="Layers from object capability to per-field visibility, data-depth scopes, audit, and an explain API" />
21+
<Card href="/docs/capabilities/analytics" title="Analytics & Dashboards" description="Chart families, period-over-period, runtime filters, TV display pages and reports" />
2222
<Card href="/docs/capabilities/ai" title="AI Under Governance" description="Ask questions and get charts; AI acts under the same permissions and audit as people; bring your own agent over MCP" />
2323
<Card href="/docs/capabilities/integrations" title="Integrations & Everyday Work" description="Import/export, generated APIs, webhooks, connectors, federated databases, marketplace templates, languages" />
2424
<Card href="/docs/capabilities/request-template" title="How to Request Features" description="A one-page template that turns business needs into configuration — hand it to your team or an AI agent" />

0 commit comments

Comments
 (0)