ObjectStackObjectStack

Publish, Versioning & Preview

A metadata app is versioned in your catalog while the platform moves on its own release train. Compile the app into an artifact, then pick how it reaches a running platform — installed from the catalog, or pinned as the runtime's boot artifact.

Your app and the platform move on separate clocks

A metadata app is not part of the platform. It compiles to its own immutable artifact, carries its own version, and is released by you, when you decide. The platform — the runtime image, the kernel, the plugins — is released on the ObjectStack release train. Neither version implies the other, and neither has to wait for the other.

That independence is the point of the model, and it is also the question this page answers: if the app is a separate thing, how does it get into a running platform?

The compile half is always the same:

objectstack.config.ts -> os compile -> dist/objectstack.json

The delivery half has two shapes, and picking the wrong one is the expensive mistake. Both are described below, with the rule for choosing.

The one place the two clocks touch is the artifact's declared engines.protocol range: it states which platform majors the app can run on, and a runtime outside that range refuses the app rather than half-loading it. Everything else about the two versions is independent.

The legacy direct-to-environment os publish / os rollback commands (which wrote sys_environment_revision) were removed (#2237). Publishing now goes through the package catalog: os package publish uploads a versioned package, and an environment is updated by installing a version into it. Revision-style rollback is no longer a framework CLI command — version and environment management are a Cloud control-plane concern.


The two ways in

Catalog installArtifact-pinned boot
The app arrivesafter the platform is runningat boot, as an input to the process
Named bypackage id + version (com.acme.crm@1.2.0)a URL to the compiled artifact (OS_ARTIFACT_URL)
Who picks the versionwhoever runs the install — an admin in the Console, CI calling the CLI, or the Cloud control planewhoever sets the runtime's environment (your deploy pipeline)
Switching versionsinstall another version; no restartchange the variable, restart
Apps per runtimemany, side by sideone — it is this runtime's app
Integritythe catalog is the trust boundaryoptional #sha256= pin in the URL fragment; boot is refused on mismatch
Needsa catalog the runtime can reach — or the artifact file, handed over inlinesomewhere to host the artifact file
Detail lives inthis pageArtifact-pinned boot

The rule for choosing

One question decides it:

Is this app the reason the runtime exists?

Yes — pin the artifact. The deployment defines the app, so the app belongs in the deployment's own inputs. No — install from the catalog. The runtime is a platform that receives apps, so apps arrive through a surface that stays open while it runs.

Three tie-breakers when both still look plausible:

  1. Must "which bytes is this instance running?" have exactly one auditable answer? Pin the artifact. A #sha256= fragment makes the answer verifiable, and a mismatch stops the boot instead of quietly serving something else. A catalog install is a live mutation of a running platform — the right shape for an app store, the wrong shape for a reproducible deployment.
  2. Must the app change without a restart, or must several apps share one runtime? Install from the catalog. The pinned artifact is resolved once, at boot; there is no in-place upgrade of it, by design.
  3. Is there no catalog to reach (air-gapped)? Either still works, so choose on 1 and 2 rather than on connectivity: os package install ./dist/objectstack.json hands the compiled artifact over inline with no catalog round-trip, and OS_ARTIFACT_URL=file:///srv/app/objectstack.json pins a mounted file.

Using both at once

They are not exclusive, and the combination is well-defined:

  • A pinned runtime still accepts installs. The install surface is mounted independently of how the runtime obtained its own app, so a runtime booted from OS_ARTIFACT_URL can still receive catalog installs — of other apps.

  • Two sources naming the same app is a refusal, not a merge. An install whose manifest.id is already registered by the runtime's own boot is rejected with 409 MANIFEST_CONFLICT ("already defined by this runtime's local code") rather than overwriting it. Uninstall or unpin first; do not expect last-write-wins.

  • Artifact sources have a fixed precedence, so a container that presets one variable cannot shadow a deliberate override:

    --artifact  >  OS_ARTIFACT_URL  >  OS_ARTIFACT_PATH  >  <cwd>/dist/objectstack.json

    OS_ARTIFACT_URL also outranks an objectstack.config.ts sitting in the working directory — setting it is an instruction to boot one specific artifact, not a hint.

A catalog address is not an artifact URL. OS_ARTIFACT_URL reads a compiled artifact from wherever you host it — release storage, an object-store URL, a mounted file. The catalog's manifest endpoints answer with an API envelope that wraps the manifest, not with a bare artifact, so a catalog URL pasted into OS_ARTIFACT_URL is not a supported reference. Publish to the catalog and upload the artifact if you want both doors open.


1. Compile

os compile
# -> dist/objectstack.json

The artifact contains metadata, manifest requirements, and packaged function code. Deployment config stays outside the artifact: database URLs, secrets, runtime credentials, and environment identity are host inputs.

This one artifact feeds both delivery shapes — it is what os package publish uploads, and it is what an artifact host serves to OS_ARTIFACT_URL.


2. Publish a package version

# upload dist/objectstack.json as a new version in your org catalog
os package publish

# explicit artifact + install into an environment in one step
os package publish ./dist/objectstack.json --env env_prod --install

The CLI:

  1. POST /api/v1/cloud/packages — ensure a sys_package row exists (id derived from artifact.manifest.id, or --manifest-id).
  2. POST /api/v1/cloud/packages/:id/versions — snapshot dist/objectstack.json into sys_package_version.manifest_json (status published).
  3. (optional) install the new version into --env.

Common flags:

FlagEnv varPurpose
artifact (positional)Path to the compiled artifact (default dist/objectstack.json)
--server, -sOS_CLOUD_URLCloud control-plane URL
--token, -tOS_CLOUD_API_KEYBearer token (service mode)
--version, -vSemver version (default: artifact.manifest.version)
--visibilityorg (default) · private · marketplace
--orgOS_ORG_IDOwner org id (service mode)
--envOS_ENVIRONMENT_IDEnvironment to install the new version into
--installAuto-install the new version into --env after publishing

In user mode the package is owned by your active organization; in service mode (bearer key) pass --org. See Packages for the package model.

Publishing changes nothing that is running. It puts a version in the catalog; step 3 is what moves an app.


3. Install a version

Two install targets, same catalog:

Into a Cloud environment — either at publish time with --env --install, or separately through the Cloud control plane / Marketplace. To "roll back," install the prior version; there is no revision-activate CLI command anymore.

Into a running runtime you operateos package install calls that runtime's local install endpoint, which registers the app into the live kernel and caches the manifest on disk so the install survives a restart:

# catalog mode: the target runtime fetches the version from its own catalog
os package install com.acme.crm --version 1.2.0 --runtime https://app.example.com

# air-gapped mode: the artifact is read locally and sent inline, no catalog
os package install ./dist/objectstack.json

This authenticates against an account on the target runtime, not your cloud login. Uninstall removes the cached manifest; the kernel needs a restart to fully unload it, because app registration is additive.

For the full command reference — every flag, every subcommand — see the CLI reference.


4. Preview patterns

Use one of these shapes:

PatternCommand
Local artifact previewos dev --artifact ./dist/objectstack.json --ui
Production artifact hostOS_ARTIFACT_PATH=./dist/objectstack.json os start
Pinned, exactly as production runs itOS_ARTIFACT_URL="file://$PWD/dist/objectstack.json" os start
Cloud environment previewInstall to a preview environment, then route clients to it via /api/v1/environments/:environmentId/... or X-Environment-Id.

The third shape is worth using before a pinned rollout: it exercises the same boot path production will take, including the engines.protocol handshake and the boot-time schema-drift policy, against a local file.


On this page