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.jsonThe 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 install | Artifact-pinned boot | |
|---|---|---|
| The app arrives | after the platform is running | at boot, as an input to the process |
| Named by | package id + version (com.acme.crm@1.2.0) | a URL to the compiled artifact (OS_ARTIFACT_URL) |
| Who picks the version | whoever runs the install — an admin in the Console, CI calling the CLI, or the Cloud control plane | whoever sets the runtime's environment (your deploy pipeline) |
| Switching versions | install another version; no restart | change the variable, restart |
| Apps per runtime | many, side by side | one — it is this runtime's app |
| Integrity | the catalog is the trust boundary | optional #sha256= pin in the URL fragment; boot is refused on mismatch |
| Needs | a catalog the runtime can reach — or the artifact file, handed over inline | somewhere to host the artifact file |
| Detail lives in | this page | Artifact-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:
- 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. - 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.
- 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.jsonhands the compiled artifact over inline with no catalog round-trip, andOS_ARTIFACT_URL=file:///srv/app/objectstack.jsonpins 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_URLcan still receive catalog installs — of other apps. -
Two sources naming the same app is a refusal, not a merge. An install whose
manifest.idis already registered by the runtime's own boot is rejected with409 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.jsonOS_ARTIFACT_URLalso outranks anobjectstack.config.tssitting 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.jsonThe 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 --installThe CLI:
POST /api/v1/cloud/packages— ensure asys_packagerow exists (id derived fromartifact.manifest.id, or--manifest-id).POST /api/v1/cloud/packages/:id/versions— snapshotdist/objectstack.jsonintosys_package_version.manifest_json(statuspublished).- (optional) install the new version into
--env.
Common flags:
| Flag | Env var | Purpose |
|---|---|---|
artifact (positional) | — | Path to the compiled artifact (default dist/objectstack.json) |
--server, -s | OS_CLOUD_URL | Cloud control-plane URL |
--token, -t | OS_CLOUD_API_KEY | Bearer token (service mode) |
--version, -v | — | Semver version (default: artifact.manifest.version) |
--visibility | — | org (default) · private · marketplace |
--org | OS_ORG_ID | Owner org id (service mode) |
--env | OS_ENVIRONMENT_ID | Environment to install the new version into |
--install | — | Auto-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 operate — os 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.jsonThis 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:
| Pattern | Command |
|---|---|
| Local artifact preview | os dev --artifact ./dist/objectstack.json --ui |
| Production artifact host | OS_ARTIFACT_PATH=./dist/objectstack.json os start |
| Pinned, exactly as production runs it | OS_ARTIFACT_URL="file://$PWD/dist/objectstack.json" os start |
| Cloud environment preview | Install 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.
Related
- Artifact-pinned boot — the operational detail for
OS_ARTIFACT_URL: schemes, integrity pinning, cache behaviour, pre-signed URLs - CLI reference
- Packages
- Deployment Overview
- Environment Variables
- Environment-Scoped Routing