Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .changeset/26136-objectos-cloud-naming.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
'@objectstack/cli': patch
'@object-ui/i18n': patch
'@object-ui/app-shell': patch
'@object-ui/console': patch
---

fix(cli,i18n,console): the hosted product reads "ObjectOS Cloud" everywhere a user reads it; the Community Console carries a "Powered by ObjectStack" mark

Clause-②: no
Metadata-protocol: none

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.

- **`@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.
- **`@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.
- **`@object-ui/app-shell`.** New `isDefaultProductName()`: true while the deployment carries the default `branding.productName` ("ObjectOS"), false once a runtime has pushed its own.
- **`@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.

What to do: nothing. An operator who rebrands the Console through `branding.productName` keeps a single brand line, as before.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ os explain # Explain protocol concepts on the command line
```

Cloud, package registry, secrets, and environment subcommands (`os package …`,
`os environments …`, `os login`, `os cloud …`) target an ObjectStack Cloud
`os environments …`, `os login`, `os cloud …`) target an ObjectOS Cloud
control plane.

### Package directory
Expand Down
12 changes: 6 additions & 6 deletions content/docs/deployment/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2626,7 +2626,7 @@ os doctor -v # Show fix suggestions for warnings
| `os login` | Sign in and store credentials in `~/.objectstack/credentials.json` |
| `os whoami` | Show the current authenticated user |
| `os logout` | Revoke the server session and clear local credentials |
| `os cloud login` | Sign in to ObjectStack Cloud (the hosted package registry) and store credentials in `~/.objectstack/cloud.json` |
| `os cloud login` | Sign in to ObjectOS Cloud (the hosted package registry) and store credentials in `~/.objectstack/cloud.json` |

#### `os register`

Expand Down Expand Up @@ -2727,7 +2727,7 @@ os logout

#### `os cloud login`

Signs you in to **ObjectStack Cloud** — the hosted package registry — rather
Signs you in to **ObjectOS Cloud** — the hosted package registry — rather
than to a runtime instance. It is the credential `os package publish` and the
marketplace commands use, and it lands in its own file
(`~/.objectstack/cloud.json`), separate from `os login`'s
Expand Down Expand Up @@ -2823,12 +2823,12 @@ is available in your deployment.

The two commands that move a compiled app onto a platform. They target
**different systems and authenticate as different identities**: publish uploads
to ObjectStack Cloud (the catalog), install registers an app into a **running
to ObjectOS Cloud (the catalog), install registers an app into a **running
runtime**.

| Command | Talks to | Description |
|---------|----------|-------------|
| `os package publish [artifact]` | ObjectStack Cloud | Upload a compiled artifact as a versioned package in your organization |
| `os package publish [artifact]` | ObjectOS Cloud | Upload a compiled artifact as a versioned package in your organization |
| `os package install <package>` | A running runtime | Install a package into a live kernel, from that runtime's catalog or from a local artifact |

For which one to reach for and the preview patterns around them, see
Expand Down Expand Up @@ -2882,7 +2882,7 @@ when both files' `url`s agree.
| `--display-name <name>` | — | Name shown in the Marketplace (default `artifact.manifest.name`) |
| `--description <text>` | — | Short package description |
| `--category <slug>` | — | Marketplace category slug (`crm`, `hr`, `devtools`, …) |
| `--visibility <level>` | — | `org` (installable across your organization) · `private` (explicit grants only) · `marketplace` (public after review). Omitted: not sent, so the control plane decides — an existing package keeps its visibility, a new one gets the control plane's default (`org` on ObjectStack Cloud) |
| `--visibility <level>` | — | `org` (installable across your organization) · `private` (explicit grants only) · `marketplace` (public after review). Omitted: not sent, so the control plane decides — an existing package keeps its visibility, a new one gets the control plane's default (`org` on ObjectOS Cloud) |
| `--org <id>` | `OS_ORG_ID` | `owner_org_id`. Required with a bearer key in service mode; ignored in user mode |
| `--env <id>` | `OS_ENVIRONMENT_ID` | Environment to install the new version into. Defaults to the environment [`os environments switch`](#cloud-environments) — or `os environments create --activate` — recorded **for this control plane** in `~/.objectstack/cloud.json` |
| `--install` | — | Auto-install into `--env` after publishing. With no `--env`, no `$OS_ENVIRONMENT_ID` and no active environment for this control plane, it reports that and publishes without installing |
Expand Down Expand Up @@ -3018,7 +3018,7 @@ A `404` means the target runtime does not mount `MarketplaceInstallLocalPlugin`
(from `@objectstack/cloud-connection`). The endpoint is opt-in, so a runtime
composed without it will not accept installs.

In catalog mode, a runtime connected to an ObjectStack Cloud account presents its connection credential to the cloud catalog — see [Cloud Connection](/docs/deployment/cloud-connection).
In catalog mode, a runtime connected to an ObjectOS Cloud account presents its connection credential to the cloud catalog — see [Cloud Connection](/docs/deployment/cloud-connection).

## Configuration

Expand Down
6 changes: 3 additions & 3 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ and keep loading through their barrel `index.ts`.

### Cloud — publish & install

Push a locally-built package to ObjectStack Cloud and (optionally) install it
Push a locally-built package to ObjectOS Cloud and (optionally) install it
into one of your environments in a single command. The commands below do not
share one session or one flag spelling — see [Credentials and server URL](#credentials-and-server-url).

| Command | Description |
|---------|-------------|
| `os cloud login` | Authenticate to ObjectStack Cloud (browser or `--email/--password`); writes `~/.objectstack/cloud.json` |
| `os cloud login` | Authenticate to ObjectOS Cloud (browser or `--email/--password`); writes `~/.objectstack/cloud.json` |
| `os cloud whoami` / `os cloud logout` | Inspect / clear the stored cloud session |
| `os environments create --org <id> --name <n>` | Provision a new environment (was `os projects create` before the v5.0 project → environment rename; ADR-0006, no aliases) |
| `os environments list` / `show <id>` | List / inspect your environments |
Expand Down Expand Up @@ -146,7 +146,7 @@ A code-bearing plugin — a directory carrying an `objectstack.plugin.json` mani
|---------|-------------|
| `os plugin build [dir]` | Compile a plugin into a signed-ready `.osplugin` artifact (`--entry`, `--out`, `--minify`) |
| `os plugin sign <artifact> --key <pem>` | Sign a built `.osplugin` with a publisher Ed25519 key, writing a detached `<artifact>.sig` |
| `os plugin publish [artifact]` | Publish a signed `.osplugin` to ObjectStack Cloud |
| `os plugin publish [artifact]` | Publish a signed `.osplugin` to ObjectOS Cloud |

The group has no `install`: ADR-0025 records the code-plugin install half (download, verify, materialize, load) as not yet implemented. `os plugin` (singular) is unrelated to `os plugins` (plural), oclif's plugin manager, which this package does not ship — see [`os plugins` and `os help`](#os-plugins-and-os-help-not-commands).

Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/commands/cloud/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ async function promptPassword(promptText: string): Promise<string> {

export default class CloudLogin extends Command {
static override description =
'Authenticate against ObjectStack Cloud (the hosted package registry). Stores credentials in ~/.objectstack/cloud.json.';
'Authenticate against ObjectOS Cloud (the hosted package registry). Stores credentials in ~/.objectstack/cloud.json.';

static override examples = [
'$ os cloud login',
Expand All @@ -151,7 +151,7 @@ export default class CloudLogin extends Command {
static override flags = {
url: Flags.string({
char: 'u',
description: 'ObjectStack Cloud URL (override for self-hosted control planes)',
description: 'ObjectOS Cloud URL (override for self-hosted control planes)',
default: DEFAULT_CLOUD_URL,
env: 'OS_CLOUD_URL',
}),
Expand Down Expand Up @@ -198,7 +198,7 @@ export default class CloudLogin extends Command {
const url = flags.url.replace(/\/+$/, '');

if (!flags.json) {
printHeader('ObjectStack Cloud Login');
printHeader('ObjectOS Cloud Login');
printKV('Server', url);
console.log('');
}
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/commands/cloud/logout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { printHeader, printSuccess, printError, emitJson, errorCodeFields } from
import { deleteCloudConfig, tryReadCloudConfig } from '../../utils/cloud-config.js';

export default class CloudLogout extends Command {
static override description = 'Clear stored ObjectStack Cloud credentials';
static override description = 'Clear stored ObjectOS Cloud credentials';

static override examples = ['$ os cloud logout'];

Expand All @@ -24,7 +24,7 @@ export default class CloudLogout extends Command {
const { flags } = await this.parse(CloudLogout);

try {
if (!flags.json) printHeader('ObjectStack Cloud Logout');
if (!flags.json) printHeader('ObjectOS Cloud Logout');

const config = await tryReadCloudConfig();
if (config?.token && config?.url) {
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/src/commands/cloud/whoami.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { printHeader, printKV, printSuccess, printError, emitJson, isExitSignal,
import { tryReadCloudConfig } from '../../utils/cloud-config.js';

export default class CloudWhoami extends Command {
static override description = 'Show the active ObjectStack Cloud identity';
static override description = 'Show the active ObjectOS Cloud identity';

static override examples = ['$ os cloud whoami'];

Expand All @@ -28,7 +28,7 @@ export default class CloudWhoami extends Command {
if (flags.json) {
await emitJson({ logged_in: false });
} else {
printError('Not logged in to ObjectStack Cloud. Run `os cloud login` first.');
printError('Not logged in to ObjectOS Cloud. Run `os cloud login` first.');
}
this.exit(1);
return;
Expand Down Expand Up @@ -56,7 +56,7 @@ export default class CloudWhoami extends Command {
if (flags.json) {
await emitJson({ logged_in: true, valid, url: config.url, email, userId });
} else {
printHeader('ObjectStack Cloud Identity');
printHeader('ObjectOS Cloud Identity');
printKV('Server', config.url);
if (email) printKV('Email', email);
if (userId) printKV('User ID', userId);
Expand Down
8 changes: 4 additions & 4 deletions packages/cli/src/commands/package/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,13 +298,13 @@ export default class PackagePublish extends Command {
static override flags = {
server: Flags.string({
char: 's',
description: 'ObjectStack Cloud control-plane URL (override for self-hosted registries)',
description: 'ObjectOS Cloud control-plane URL (override for self-hosted registries)',
env: 'OS_CLOUD_URL',
default: DEFAULT_CLOUD_URL,
}),
token: Flags.string({
char: 't',
description: 'API key for ObjectStack Cloud (bearer token; defaults to OS_CLOUD_API_KEY / OS_TOKEN)',
description: 'API key for ObjectOS Cloud (bearer token; defaults to OS_CLOUD_API_KEY / OS_TOKEN)',
env: 'OS_CLOUD_API_KEY',
}),
'manifest-id': Flags.string({
Expand Down Expand Up @@ -337,7 +337,7 @@ export default class PackagePublish extends Command {
"'private': only explicitly-granted orgs/envs. " +
"'marketplace': public after review. " +
'Omit it to leave an existing package\'s visibility unchanged; a new package then gets ' +
"the control plane's default ('org' on ObjectStack Cloud).",
"the control plane's default ('org' on ObjectOS Cloud).",
options: ['private', 'org', 'marketplace'],
}),
org: Flags.string({
Expand Down Expand Up @@ -517,7 +517,7 @@ export default class PackagePublish extends Command {
}
if (!token) {
printError(
'Not logged in to ObjectStack Cloud. Run `os cloud login` first, or pass --token / set $OS_TOKEN.',
'Not logged in to ObjectOS Cloud. Run `os cloud login` first, or pass --token / set $OS_TOKEN.',
);
this.exit(1);
return;
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/commands/plugin/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ interface PostResult { ok: boolean; status: number; body: any; error?: string }

export default class PluginPublish extends Command {
static override description =
'Publish a signed .osplugin to ObjectStack Cloud (ADR-0025 §3.4)';
'Publish a signed .osplugin to ObjectOS Cloud (ADR-0025 §3.4)';

static override examples = [
'$ os plugin publish ./com.acme.stripe-1.0.0.osplugin --visibility marketplace --submit',
Expand Down Expand Up @@ -72,7 +72,7 @@ export default class PluginPublish extends Command {
description:
"Who can see / install this plugin's package. " +
"Omit it to leave an existing package's visibility unchanged; a new package then gets " +
"the control plane's default ('org' on ObjectStack Cloud).",
"the control plane's default ('org' on ObjectOS Cloud).",
options: ['private', 'org', 'marketplace'],
}),
org: Flags.string({ description: 'owner_org_id (service mode)', env: 'OS_ORG_ID' }),
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6232,7 +6232,7 @@ export function createUnknownHostnameGuardPlugin(
<div class="host">${safeHost}</div>
<p class="muted" style="margin-top:24px">
If you own this domain, bind it to an environment in the
<a href="https://cloud.objectos.ai/">ObjectStack Cloud console</a>.
<a href="https://cloud.objectos.ai/">ObjectOS Cloud console</a>.
</p>
</main>
</body>
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/utils/api-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export function requireAuth(token?: string): void {
export function requireControlPlaneAuth(token?: string): void {
if (!token) {
throw new Error(
'Authentication required. Run `os cloud login` for ObjectStack Cloud or `os login` for a '
'Authentication required. Run `os cloud login` for ObjectOS Cloud or `os login` for a '
+ 'self-hosted control plane, or set OS_TOKEN.'
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/utils/cloud-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export async function readCloudConfig(): Promise<CloudConfig> {
return JSON.parse(content) as CloudConfig;
} catch (error: any) {
if (error.code === 'ENOENT') {
throw new Error('Not logged in to ObjectStack Cloud. Run `os cloud login` first.');
throw new Error('Not logged in to ObjectOS Cloud. Run `os cloud login` first.');
}
throw new Error(`Failed to read cloud credentials: ${error.message}`);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/cloud-login-json-ndjson.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ describe('os cloud login --json — the declared NDJSON stream (#6730)', () => {
// this subsumes "nothing else was written" rather than listing banners a
// future edit could add to.
expect(lines(ok.stdout)).toHaveLength(2);
expect(ok.stdout).not.toContain('ObjectStack Cloud Login');
expect(ok.stdout).not.toContain('ObjectOS Cloud Login');
expect(ok.stdout).not.toContain('To authorize this CLI');
expect(ok.stdout).not.toContain('Waiting for browser approval');
expect(ok.stdout).not.toContain('Credentials stored in');
Expand Down
61 changes: 61 additions & 0 deletions packages/cli/test/cloud-product-name.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.

/**
* The hosted product reads "ObjectOS Cloud" wherever the CLI names it.
*
* ObjectOS is the product, in three editions (Community, Cloud, Enterprise);
* ObjectStack is the protocol, SDK, CLI and framework. The strings a user
* reads from the cloud commands — the command descriptions `--help` prints,
* the flag descriptions, the "not logged in" prescriptions — name the hosted
* product by its product name. Internal identifiers keep theirs:
* `~/.objectstack/cloud.json`, `OS_CLOUD_API_KEY`, `os cloud login`.
*
* Pinned on the command classes' own statics rather than on a spawned
* `--help`: it is the same text oclif prints, read without a process.
*/

import { describe, it, expect } from 'vitest';
import CloudLogin from '../src/commands/cloud/login.js';
import CloudLogout from '../src/commands/cloud/logout.js';
import CloudWhoami from '../src/commands/cloud/whoami.js';
import PackagePublish from '../src/commands/package/publish.js';
import PluginPublish from '../src/commands/plugin/publish.js';

const COMMANDS = [CloudLogin, CloudLogout, CloudWhoami, PackagePublish, PluginPublish] as const;

/** Every user-readable string a command's help carries: its description and its flags'. */
function helpStrings(command: (typeof COMMANDS)[number]): string[] {
const flags = Object.values(command.flags ?? {}) as Array<{ description?: string }>;
return [command.description ?? '', ...flags.map((flag) => flag.description ?? '')];
}

describe('cloud commands name the hosted product "ObjectOS Cloud"', () => {
it('names it in the login, logout and whoami descriptions', () => {
expect(CloudLogin.description).toContain('ObjectOS Cloud');
expect(CloudLogout.description).toContain('ObjectOS Cloud');
expect(CloudWhoami.description).toContain('ObjectOS Cloud');
});

it('names it in the control-plane URL and API-key flag descriptions', () => {
expect(CloudLogin.flags.url.description).toContain('ObjectOS Cloud');
expect(PackagePublish.flags.server.description).toContain('ObjectOS Cloud');
expect(PackagePublish.flags.token.description).toContain('ObjectOS Cloud');
expect(PackagePublish.flags.visibility.description).toContain('ObjectOS Cloud');
expect(PluginPublish.description).toContain('ObjectOS Cloud');
expect(PluginPublish.flags.visibility.description).toContain('ObjectOS Cloud');
});

it('carries no "ObjectStack Cloud" in any help string of those commands', () => {
const stale = COMMANDS.flatMap((command) =>
helpStrings(command)
.filter((text) => text.includes('ObjectStack Cloud'))
.map((text) => `${command.id ?? command.name}: ${text}`),
);
expect(stale).toEqual([]);
});

it('keeps the internal identifiers as they are', () => {
expect(CloudLogin.description).toContain('~/.objectstack/cloud.json');
expect(PackagePublish.flags.token.description).toContain('OS_CLOUD_API_KEY');
});
});
2 changes: 1 addition & 1 deletion scripts/sdui-manifest.sources/i18n.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"package":"ui/packages/i18n","sources":31,"sha256":"83894d7c91938618b320bda4f6664c1b39a0d5d6e7c3238e8e5eac5c51e1ec39","manifestSha256":"1f6e1ccb925a678eaa393f9091dfc7d0285e4e3626e0a5c61a5474687debabb7"}
{"package":"ui/packages/i18n","sources":31,"sha256":"4bcb36ff124e98b8405929277c2acd9afdeb73347b814df67cf26a80727996af","manifestSha256":"1f6e1ccb925a678eaa393f9091dfc7d0285e4e3626e0a5c61a5474687debabb7"}
Loading
Loading