Build, publish, and upgrade
The Workspace UI Project separates three deliberate steps: check the source, build an immutable artifact, and activate that artifact for end users. A save is not a deploy and a successful build is not a release. Workspace UI code is trusted workspace code compiled by Moltaro — the boundary is governance and review (permissions, immutable revisions, audited activation), not a hostile-code sandbox.
Everything on this page is available in the Constructor area — UI Studio
(/business-logic/ui-development) and UI Project
(/business-logic/ui-project), group Automation & logic — and through
the admin API under /api/workspace/admin/ui-project, part of the
Configuration API.
UI Studio shows Draft — publish required whenever its working revision is
not the active artifact. That status opens UI Project, so the path from a newly
created page to Build and Activate remains visible without relying on hidden
toolbar actions.
Checks and builds
Section titled “Checks and builds”POST /builds queues one operation for one immutable source revision. The
request requires a RevisionId — there is no implicit “latest source” build
— and a Kind:
- Check (
Kind= 0) validates the revision through the compile pipeline and produces no artifact. - Build (
Kind= 1) runs the same pipeline and stores a successful result as an inactive immutable artifact.
Builds run in the background; the build record reports Status (Queued,
Running, Succeeded, Failed, Cancelled), Stage, and ProgressPercent.
Structured compiler diagnostics stay attached to the build record — code,
severity, stage, message, path, and line/column positions — so a failure is
inspectable later without re-running it. A failed check or build never
replaces the active artifact: whatever users currently see keeps running.
Explicit activation
Section titled “Explicit activation”Exactly one artifact is active at a time. A successful build changes nothing
for end users until a caller with the Publish permission activates the
artifact. Activation is audited, is rejected for artifacts that do not match
the current host contract, and returns RefreshRequired — already-open
sessions keep the previous UI until a full WebApp refresh, while new sessions
load the new artifact. Active pages are served under /apps/<pageKey> as
“Workspace page” and can be linked from user menus as “Workspace UI page”
leaves (see User menus).
Three more lifecycle operations complete the picture:
- Deactivate takes the currently active artifact out of service; end-user pages become unavailable until another activation.
- Rollback restores a compatible previously published artifact — the fast path back when a release misbehaves.
- Purge deletes the stored JavaScript/CSS bytes of an inactive artifact while retaining its history metadata (hashes, sizes, versions, publisher).
Artifact state changes carry expected project and artifact row versions and fail with a conflict when concurrent administration changed state first.
Compatibility after a Moltaro update
Section titled “Compatibility after a Moltaro update”Each artifact records the WebApp version, host contract version, and
toolchain fingerprint it was built with. GET /compatibility reports whether
the packaged build toolchain and runtime contract are ready and, with
?artifactId=, whether one stored artifact still matches the current host
contract (IsCompatible, CanActivate, CanRollback, plus safe localized
diagnostics).
After a Moltaro update, the active artifact may no longer match the new host contract. Source revisions are stored server-side, so the remedy is a rebuild from the stored source followed by a new activation. A breaking host-contract change can additionally require source edits before the rebuild succeeds; the check pipeline and its diagnostics report exactly what broke.
If the active artifact is runtime-incompatible, only its custom /apps/*
pages are unavailable; core Moltaro remains usable. Fix any source diagnostics,
run Build, review the newly stored inactive artifact, Activate explicitly, and
then perform a full browser refresh. Failed or stale checks/builds preserve the
source revisions, history, and prior artifact, and no update or build
auto-activates output.
Endpoints and permissions
Section titled “Endpoints and permissions”All routes live under /api/workspace/admin/ui-project and are gated by the
Workspace UI Project permission group — View, Manage source,
Build, Publish. Owner, Admin, and Configurator hold all of them
implicitly.
| Endpoint | Permission | Purpose |
|---|---|---|
GET /status | any of the group | Project status; provisions the empty six-file system skeleton for source-capable callers |
GET /revisions, GET /revisions/{revisionId} | View, Manage source, or Build | Immutable source revisions, newest first |
GET /source-tree | Manage source | Source-tree metadata for one revision |
GET /source-files | Manage source | One UTF-8 source file by revision and path |
POST /source-revisions/manual-edit | Manage source | Create one immutable manual-edit revision |
GET /source-templates | Manage source | Deterministic source templates |
POST /source-templates/preview, POST /source-templates/apply | Manage source | Preview, or apply a template as one revision |
GET /page-generators/catalog | Manage source | Typed page-generator, entity-field, and working-page capabilities |
POST /page-generators/preview, POST /page-generators/apply | Manage source | Preview or apply one generated page; menu placement needs a trusted role |
DELETE /revisions/{revisionId} | Manage source | Delete a disposable revision and its non-artifact build history |
GET /download | Manage source | Deterministic source and generated IDE-project ZIP |
POST /upload | Manage source | Upload a ZIP as one immutable revision, without auto-queuing a build |
GET /builds, GET /builds/{buildId} | View or Build | Check and build history with diagnostics |
POST /builds | Build | Queue a check or build for one revision |
POST /builds/{buildId}/cancel | Build | Request cancellation of a queued or running build |
GET /artifacts, GET /artifacts/{artifactId} | View or Publish | Stored artifacts, newest first |
GET /compatibility | View or Publish | Toolchain, runtime-contract, and optional artifact compatibility |
POST /artifacts/{artifactId}/activate | Publish | Activate one compatible inactive artifact |
POST /artifacts/{artifactId}/deactivate | Publish | Deactivate the currently active artifact |
POST /artifacts/{artifactId}/rollback | Publish | Roll back to a compatible previously published artifact |
POST /artifacts/{artifactId}/purge | Publish | Purge bytes from an inactive artifact, retaining history metadata |
Authoring through the API
Section titled “Authoring through the API”The full authoring loop works headlessly with a service-account API key sent
as Authorization: Bearer <api-key> (see the
integration quickstart). Enums are
serialized as numbers; the OpenAPI document names each value through
x-enum-varnames.
1. Read the project state (View). GET /status returns the project
status and, for source-capable callers, provisions only workspace-ui.json
plus the five empty locale files on first call. It never creates sample pages,
stores, clients, translations, or a README.
2. Read the source (Manage source). GET /source-tree lists file
metadata for the working or a requested revision; GET /source-files?path=src/pages/MachineStatusPage.vue returns one UTF-8 file.
3. Edit (Manage source). Create an immutable revision from file changes:
POST /api/workspace/admin/ui-project/source-revisions/manual-editAuthorization: Bearer <api-key>Content-Type: application/json{ "BaseRevisionId": "0197f2…", "BaseSourceChecksum": "5f8a…", "Comment": "Add machine status page", "Changes": [ { "Operation": 0, "Path": "src/pages/MachineStatusPage.vue", "ContentUtf8": "<template>…</template>" } ]}Operation 0 upserts, 1 renames (with NewPath), 2 deletes. Alternatives
that also produce one immutable revision: POST /source-templates/apply,
POST /page-generators/apply, or POST /upload with a ZIP. Each response —
like GET /revisions — carries the new revision Id.
4. Check, then build (Build). RevisionId is required; a null value is
rejected. Queue a check first ("Kind": 0), and once it passes, a build:
{ "RevisionId": "0197f3…", "Kind": 1 }The response is the queued build record with its Id.
5. Poll the build (View or Build). GET /builds/{buildId} until Status
is 2 (Succeeded), 3 (Failed), or 4 (Cancelled). On failure, read the attached
diagnostics:
{ "Status": 3, "ErrorSummary": "1 error", "Diagnostics": { "Diagnostics": [ { "Code": "TS2304", "Severity": 2, "Message": "Cannot find name 'refx'.", "Path": "src/pages/useMachineStatusPage.ts", "StartLine": 12 } ] }}6. Find the artifact (View or Publish). GET /artifacts lists stored
artifacts newest first; match the new one by its BuildId and RevisionId.
It is inactive until published.
7. Activate (Publish):
POST /api/workspace/admin/ui-project/artifacts/{artifactId}/activate{ "ExpectedProjectRowVersion": "…", "ExpectedArtifactRowVersion": "…" }The result reports RefreshRequired: true.
8. Tell users to refresh. Open sessions keep the previous UI until a full
WebApp refresh; after refreshing, users see the new pages under
/apps/<pageKey>.
An authoring declaration update can change the host fingerprint even while
HostContractVersion remains 1. For example, the typed grid
getColumnState() method and the embedded-component contract
(Components registration, useComponentContext()) each required an updated
declaration. After installing
the corresponding Moltaro build, refresh the IDE project files, check and
rebuild existing source, activate the compatible artifact, and fully refresh
the browser. Do not change fingerprints manually or reuse an older artifact
to bypass compatibility validation. Template improvements do not rewrite your
saved source; copy the required explicit attach bindings into existing pages.