Skip to content

Commit f19c814

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/project-thread-r8r6to
2 parents 69181bf + 46255b1 commit f19c814

131 files changed

Lines changed: 4205 additions & 1423 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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@object-ui/auth': patch
3+
'@object-ui/console': patch
4+
---
5+
6+
fix(auth,console): the sign-up form shows a password mismatch under the confirm field, and the register page links privacy and terms
7+
8+
Clause-②: no
9+
Metadata-protocol: none
10+
11+
- **Mismatch on the field.** `RegisterForm` showed "Passwords do not match" as the error banner at the top of the form, above the name field. The message now sits under the confirm-password input, which carries `aria-invalid` and names the message through `aria-describedby`. Editing either password clears it. The banner still carries what the server refuses (an existing account, a closed registration). The text is the same `labels.passwordMismatchError`, so no locale key changes. Every page that renders `RegisterForm` gets this.
12+
- **Legal links on sign-up.** The console's `/register` now draws the same footer as `/login`: the locale switch, plus the privacy and terms links that `GET /api/v1/auth/config` serves as `features.privacyUrl` / `features.termsUrl`. A link appears only when its URL is served and is an http(s) URL or a same-origin path. Both pages now read the links through one shared reader.
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+
refactor(app-shell): the Console `ObjectView`'s leaf pieces move into a sibling module
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
The "object not found" state (`ObjectNotFoundState`), the viewport check that decides whether the saved-view tab strip is drawn, and the inline-edit toggle's session-only callback move verbatim out of `views/ObjectView.tsx` into `objectViewChrome.tsx` beside it. No logic, name or rendered output changes. `ObjectView.tsx` re-exports every name it exported before, and the package entry is unchanged.
11+
12+
What to do: nothing.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
'@objectstack/cli': patch
3+
'@object-ui/i18n': patch
4+
'@object-ui/app-shell': patch
5+
'@object-ui/console': patch
6+
---
7+
8+
fix(cli,i18n,console): the hosted product reads "ObjectOS Cloud" everywhere a user reads it; the Community Console carries a "Powered by ObjectStack" mark
9+
10+
Clause-②: no
11+
Metadata-protocol: none
12+
13+
ObjectOS is one product in three editions — Community (this repository's runtime and Console, open source), Cloud (cloud.objectos.ai) and Enterprise — and ObjectStack is the name of the protocol, SDK, CLI and framework. The hosted product is "ObjectOS Cloud" wherever a user reads it; it was still "ObjectStack Cloud" in the CLI and in the Console's cloud-install strings.
14+
15+
- **`@objectstack/cli`.** `os cloud login`, `os cloud logout`, `os cloud whoami`, `os package publish` and `os plugin publish` say "ObjectOS Cloud" in their `--help` descriptions, their `--url` / `--server` / `--token` / `--visibility` flag descriptions, their headers and their "Not logged in" prescriptions; so do the `os serve` welcome page's link to the cloud console and the shared "Authentication required" message. The CLI README and the deployment CLI reference follow. Internal identifiers are unchanged: `~/.objectstack/cloud.json`, `OS_CLOUD_API_KEY`, `OS_CLOUD_URL`, the `os cloud …` command names.
16+
- **`@object-ui/i18n`.** The cloud-connection "Connected to …" title and the three cloud-install dialog sentences ("You need to be signed into …", "… sign into … first") name "ObjectOS Cloud" in all ten locales, the product name kept untranslated inside each locale's sentence. New key `auth.shell.poweredBy` ("Powered by ObjectStack") in all ten locales.
17+
- **`@object-ui/app-shell`.** New `isDefaultProductName()`: true while the deployment carries the default `branding.productName` ("ObjectOS"), false once a runtime has pushed its own.
18+
- **`@object-ui/console`.** The sign-in layout (login, register, forgot/reset password, verify email, setup, consent, device, invitation) shows a small "Powered by ObjectStack" link to objectstack.ai under the form when `isDefaultProductName()` is true. A deployment that pushes its own product name — ObjectOS Cloud, Enterprise, a cloud-connected workspace — shows its own name and no second brand line. The default product name, `logo.svg`, `manifest.json` and `admin@objectos.ai` are unchanged.
19+
20+
What to do: nothing. An operator who rebrands the Console through `branding.productName` keeps a single brand line, as before.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
'@object-ui/console': patch
4+
---
5+
6+
fix(app-shell,console): one app opens under one address — a name-alias route moves onto the package id
7+
8+
Clause-②: no
9+
Metadata-protocol: none
10+
11+
An app with a package id answered under two address families in one session. ADR-0048 keys `/apps/<segment>` on the package id, and every sidebar entry builds on it, but the app's `name` still resolves as an alias, and a page opened on the alias built every link of its own (list rows, record pages, related lists) on the alias. Landing on `/apps/clm/…` therefore opened contracts under the name and obligations and the approvals inbox under `/apps/app.objectstack.hotclm/…`.
12+
13+
- **`@object-ui/app-shell`:** a route under `/apps/<name>/…` whose app carries a package id is rewritten, with `replace`, to the same path under `/apps/<package id>/…`, keeping the query string, hash and history state. Old name-based bookmarks and shared links keep opening, now on the one address. The top-bar logo and every Home affordance (`resolveDeclaredHomePath`) name the declared app by its package id. An app without a package id, an app whose name is its package id, and every app after the first of a package that ships several (the package id opens the first) keep their name as their address.
14+
- **`@object-ui/console`:** the `/` landing (`resolveLandingPath`) names the landing app by the same address, so post-login and the logo agree and no redirect hop follows.
15+
16+
What to do: nothing. Links that name an app by its name keep working; they now arrive on its package-id address.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
'@objectstack/metadata-protocol': patch
3+
'@objectstack/plugin-security': patch
4+
'@objectstack/spec': patch
5+
---
6+
7+
fix(metadata-protocol)!: a permission set that grants a hierarchy scope is refused on publish, and warned on a draft save, when the runtime mounts no hierarchy resolver; explain names the absent resolver (#26188)
8+
9+
Clause-②: yes (narrowing: on a runtime with no hierarchy resolver, publishing a permission set whose grant uses `own_and_reports`, `unit` or `unit_and_below` is refused, where it used to answer 200; widened: `@objectstack/spec/security` gains the export `findHierarchyScopeGrants`, and `@objectstack/plugin-security`'s `ExplainEngineDeps` gains the optional member `hierarchyResolverMounted`)
10+
Metadata-protocol: none
11+
Ruling-ref: #26059 ruling Q3 / Q4 (`6416233738`), items 9a and 9b of the item reading (`6415971852`)
12+
13+
`own_and_reports`, `unit` and `unit_and_below` are enforced only by the enterprise hierarchy resolver (capability `hierarchy-security`, ADR-0057). Without it the open sharing service evaluates them as `own`. `defineStack` already refuses such a grant unless the stack declares `requires: ['hierarchy-security']`, but a runtime save of the same permission set answered 200 with no word, and explain then told a manager that a subordinate's record was outside their unit.
14+
15+
What changes:
16+
17+
- The runtime authoring gate reads whether a hierarchy resolver is mounted (the kernel service `hierarchy-scope-resolver`) on every metadata write. When none is, a permission set whose `readScope` or `writeScope` is a hierarchy depth is refused on publish: a direct active save, the per-item publish of a draft, the package batch publish and a restore to such a version all answer 422 `INVALID_METADATA`, with one `issues[]` entry per grant under the rule `hierarchy-scope-capability-required`. The entry is located at the grant and names the `hierarchy-security` requirement.
18+
- A draft save of the same body still succeeds. Its answer carries the same finding, at `severity: 'warning'`, in `advisories`.
19+
- With a resolver mounted, nothing changes. A host with no service registry (the CLI) judges nothing here; `defineStack` is that host's door.
20+
- `explainAccess`: on a deployment with no resolver, the depth layer's record cell for a hierarchy read depth now reads "Hierarchy resolver absent — requires enterprise; depth evaluated as 'own'." instead of saying the owner is outside the caller's read depth.
21+
- `@objectstack/spec/security` exports `findHierarchyScopeGrants`, the one list of hierarchy depths and the one finding sentence. `defineStack`'s refusal reads it too, and its message is unchanged.
22+
23+
**BREAKING** for a runtime with no hierarchy resolver that publishes hierarchy-scope grants at runtime.
24+
25+
- **Before.** The publish answered 200 and the grant was enforced as owner-only.
26+
- **Now.** The publish answers 422 `INVALID_METADATA` with the rule `hierarchy-scope-capability-required`. A draft save warns.
27+
- **Fix.** Set the grant's `readScope` / `writeScope` to `own` or `org`, or run the permission set on a runtime that mounts the enterprise hierarchy resolver (`hierarchy-security`). Rows already stored are read as before.
28+
29+
<!-- adr-0087: not-required (no-migration-prescription) a run-time narrowing at the metadata publish door, conditional on a deployment fact (no hierarchy resolver mounted). No authorable key, spelling or stored shape moves: the permission-set schema parses exactly as before, `defineStack` already refused the same grant, and no stored row is read, rewritten or converted. The repair is the author's choice between a non-hierarchy depth and an enterprise runtime, which no ledger entry can derive. The other categories are closed on facts: the packages publish (not unpublished); no ADR-0087 id covers this verdict (not already-registered); the one spec export is added, not moved, renamed or removed; and nothing a stored artifact carries changes type, so no conversion has a source to rewrite. -->
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
'@objectstack/formula': patch
3+
'@objectstack/service-automation': patch
4+
'@object-ui/core': patch
5+
'@object-ui/react': patch
6+
---
7+
8+
fix(formula,core,react): a template's formatter locale comes from a reserved context channel, so a root named `locale` is just a value, and the console passes the viewer's display locale
9+
10+
Clause-②: yes (narrowing)
11+
Metadata-protocol: none
12+
13+
<!-- adr-0087: not-required (no-migration-prescription) No metadata moves: no spec key, authorable spelling, object definition, stored row or stored shape is added, removed, renamed or re-shaped. What changes is which input sets the template dialect's formatter locale: the evaluate context's own `locale` field instead of a root named `locale`. A template that names a root `locale` keeps compiling and rendering; its hole still prints that value, only the number and date formatting no longer follows it. There is nothing for `objectstack migrate meta` to rewrite. The other categories are closed on facts: every package publishes (not unpublished); no ADR-0087 id is named or touched (not registered or already-registered); and no runtime interface, type or export is removed or narrowed: `EvalContext` gains an optional member and `fillTemplateHoles` an optional trailing argument (not runtime-interface-only, type-surface-only or runtime-export-retired). -->
14+
15+
The `template` dialect's formatters (`number`, `currency`, `percent`, `date`, `datetime`) used to take their locale from `extra.locale`, the same bag a caller passes the template's roots in. A template's roots are author-visible values, so a bulk action param or a flow variable named `locale` silently set the locale of every formatted value in the sentence, and no caller ever passed the viewer's locale.
16+
17+
- **`@objectstack/formula`**: `EvalContext` gains `locale?: string`, a reserved channel like `timezone`. It is not bound as a variable, and the template engine reads its formatter locale from it alone, defaulting to `en-US` when unset or empty. `extra.locale` is no longer read.
18+
- **`@objectstack/service-automation`**: a flow text slot's formatters render in `en-US`, and a flow variable named `locale` is a value like any other. The renderer's doc said the variable was also the formatters' locale; that line is gone.
19+
- **`@object-ui/core`**: `fillTemplateHoles(source, roots, locale?)` passes `locale` on the engine's reserved channel, apart from the roots. `ActionRunner.setDisplayLocale(read)` installs where the runner reads the viewer's display locale; `confirmText` and `successMessage` templates format in it, and a `callContext` dispatch keeps it.
20+
- **`@object-ui/react`**: `<ActionProvider>` and `useActionRunner` install `useDisplayLocale()` on the runner they build, read when a template is filled, so a locale switch reaches a runner built before it.
21+
22+
**BREAKING** (a narrowing) for a caller that set the formatter locale through a root: a template evaluated with `extra: { locale }` (or a flow variable named `locale`) now formats in `en-US` and prints the value only where a hole names it. None was found in this repository: the one test that did so now passes `locale` on the context. What to do: pass the locale as the evaluate context's `locale` (`templateEngine.evaluate(expr, { extra: roots, locale })`), or as `fillTemplateHoles`'s third argument.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
'@objectstack/cli': patch
3+
---
4+
5+
fix(cli): a direct `os serve --dev` compiles the config before its dev artifact door serves it, so the served connector `baseUrl` is the one dispatch calls
6+
7+
Clause-②: no
8+
Metadata-protocol: none
9+
10+
- **Before.** `os serve --dev` over an existing `dist/objectstack.json` served that file through the dev artifact door as found, while dispatch read the config module it evaluated. A config value read from the environment, such as `examples/app-showcase`'s self URL built from `OS_PORT`, then differed between them. With `OS_PORT=41302` over an artifact built without it, `GET /api/v1/meta/connector/showcase_status_api` served `http://127.0.0.1:3000` while the connector called port 41302. `os dev` had the same split until it began compiling at boot.
11+
- **Now.** Before it composes that door, a direct dev boot compiles the config into the artifact in its own environment, using the same decision `os dev` uses (`devCompilesAtBoot`), so both copies come from one evaluation. A failed compile refuses the boot, as under `os dev`. This costs about 3 s per boot on the showcase.
12+
- Under `os dev`, the `serve` child keeps its parent's decision and never compiles again, so `os dev --no-compile` still boots the artifact as built. A dev boot with no artifact on disk composes no door and compiles nothing, as before. A pinned artifact (`OS_ARTIFACT_URL`) is never rebuilt.
13+
- Production `os serve` (no `--dev`, `NODE_ENV` not `development`) and `os start` are unchanged.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
'@object-ui/app-shell': patch
3+
'@object-ui/components': patch
4+
'@object-ui/fields': patch
5+
'@object-ui/plugin-calendar': patch
6+
'@object-ui/plugin-charts': patch
7+
'@object-ui/plugin-chatbot': patch
8+
'@object-ui/plugin-dashboard': patch
9+
'@object-ui/plugin-editor': patch
10+
'@object-ui/plugin-form': patch
11+
'@object-ui/plugin-gantt': patch
12+
'@object-ui/plugin-grid': patch
13+
'@object-ui/plugin-kanban': patch
14+
'@object-ui/plugin-map': patch
15+
'@object-ui/plugin-markdown': patch
16+
'@object-ui/plugin-timeline': patch
17+
'@object-ui/plugin-tree': patch
18+
'@object-ui/plugin-view': patch
19+
'@object-ui/providers': patch
20+
'@object-ui/react': patch
21+
'@object-ui/react-runtime': patch
22+
'@object-ui/sdui-parser': patch
23+
'@object-ui/types': patch
24+
---
25+
26+
chore(ui): every ui package whose `test` script calls `vitest` now declares `vitest` as a devDependency, so `pnpm --filter @object-ui/PKG test` runs from the repository root
27+
28+
Clause-②: no
29+
Metadata-protocol: none
30+
31+
The package `test` scripts run `vitest run --root ../.. packages/PKG/`. A pnpm script resolves its binaries from the package's own `node_modules/.bin` and the workspace root's, and vitest was installed only under `ui/node_modules/.bin`, so 24 of the 41 ui packages with a `test` script failed with `vitest: not found` from both the repository root and `ui/`. Each of them now declares `vitest: ^4.1.10`, the range `ui/package.json` and the other 17 packages already declare; the lockfile resolves every new entry to the snapshot those packages already use, so no package gains a copy. Nothing a consumer installs changes: only the `devDependencies` field of the published `package.json` moves.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@objectstack/platform-objects': patch
3+
---
4+
5+
fix(platform-objects): a business unit membership is titled by the person's and the unit's names, not their ids
6+
7+
Clause-②: no (no exported type, schema field or spec key changes; `sys_business_unit_member.display_title` stays a text formula and `titleFormat` is unchanged)
8+
Metadata-protocol: none
9+
10+
`sys_business_unit_member.display_title`, the record title Setup → Business Unit Members shows in its Title column and on the record heading, read `record.user_id + ' in ' + record.business_unit_id`, so it showed two raw ids. It now reads the user's name (their email where the name is blank) and the business unit's name, one hop through each lookup, the traversal the formula read path already serves (ADR-0079 addendum, 2026-10-18), as `sys_user_permission_set`'s title does. The title reads "Ada Lovelace in EMEA Sales".
11+
12+
Nothing is stored and no hook is added: a write costs nothing more, and a read that serves the title makes one batched read of `sys_user` and one of `sys_business_unit` per page. A renamed user or unit, or a membership moved to another user or unit, shows the new names on the next read. Both hops are read with the reader's permissions: where the reader may not read the user or the unit, or it no longer exists, the title is empty and the console falls back to `titleFormat`. The title is still not sortable or searchable, as before.

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ os explain # Explain protocol concepts on the command line
254254
```
255255

256256
Cloud, package registry, secrets, and environment subcommands (`os package …`,
257-
`os environments …`, `os login`, `os cloud …`) target an ObjectStack Cloud
257+
`os environments …`, `os login`, `os cloud …`) target an ObjectOS Cloud
258258
control plane.
259259

260260
### Package directory

0 commit comments

Comments
 (0)