Repository navigation
zen 1.2.0
Back up the files you added to the install directory before running zen app update (zen CLI
1.2.0). zen 1.2.0 deletes every file at the top level of the install directory that is not part
of the release artifact: secrets.enc (even when Auth:Secrets:EncryptedFile:SecretsFile points
at it), .mcp.json, mcp-auth.sh, .license-activated, and any notes or scripts you put there.
appsettings.user.yaml is kept. The deleted files are not in the rollback snapshot, so
zen app rollback cannot restore them, and the CLI starts the service anyway and reports success.
Until a fixed CLI release ships:
- Immediately before the update, copy every file you added to the top level of the install
directory to a directory outside it, keeping ACLs and ownership. Windows:
robocopy <install-dir> <backup-dir> /COPYALL /LEV:1. Linux:
sudo find <install-dir> -maxdepth 1 -type f -exec cp -a -t <backup-dir> {} +.
Alternatively, move the secrets store out of the install directory: stop the service, move
secrets.encinto the data directory (keeping its ACL), point
Auth:Secrets:EncryptedFile:SecretsFileat the new location (a relative value resolves against
Storage:Directory), and start the service. zen app updatestarts the service itself. Right after it finishes, check thatsecrets.enc
and your other files are still present. If any is missing, stop the service, copy the files back
with their ACLs (Windows:robocopy <backup-dir> <install-dir> secrets.enc .mcp.json mcp-auth.sh /COPYALL;
Linux:sudo cp -a), and start the service again. Runs that started without the secrets store
fail withSecret not foundand need to be re-run.
Copying the bytes back is not enough on Windows if the file had an explicit ACE for the service
account: the ACE is lost with the deleted file, and writing secrets fails until it is granted
again. /COPYALL preserves it.
zen is the Zenvara command-line interface — a single self-contained native binary (NativeAOT, no
.NET runtime required) for installing, operating, and talking to a Zenvara instance.
This release adds typed scripting verbs for the platform (zen entity, zen flow run, zen whoami,
zen diagnostics version) and continues the install-safety work of 1.1.0. Read the breaking changes
before upgrading — several of them turn an install that used to succeed (or half-succeed) into a
refusal, which is the point, but it will surface in automation.
The new scripting verbs need Zenvara server 3.1.0 or later. Everything else works against any
server 1.1.0 worked against.
Breaking changes
-
zen service install --service-passwordis removed. The password is now prompted for (masked)
when--service-usernames a real account, or read as one line of strict UTF-8 from stdin for
scripts:cmd /c "zen service install … --service-user .\svc < pw.txt". It used to be visible in
process command lines and in Security event 4688. A leftover script still passing the flag is
refused with a fixed message that does not echo your command line. -
An operator-chosen
--data-dirnow has its DACL replaced.zen service installand
zen iis installbreak inheritance on it and grant only the service identity, Administrators and
SYSTEM. Another service or user that relied on access to that directory loses it — if two
installs share a data directory today, give each its own--data-dirbefore upgrading. The
install refuses (exit non-zero, nothing written) when the directory is a volume root or
machine-wide location, contains or is the application directory, holds any entry owned by an
untrusted principal or carrying its own broad Allow ACE, or cannot be fully inspected. The shared
%ProgramData%\Zenvara\datadefault is still never re-DACLed, and now says so loudly. -
A
--data-dirthis run will not apply is refused. Passing a different--data-dirthan the
one already configured, without--force, now exits 1 instead of exiting 0 while granting
permissions on a directory the server would not use. Re-passing the same--data-diris
unaffected. A config with noStorage:block at all now gets one written, without--force. -
A refused
zen iis installcreates nothing. It used to exit 1 with the site and app pool
created and started; it now exits 1 having created neither. -
Install names are stricter.
zen service install --nameandzen iis install --namerefuse
empty or all-dot names, Windows reserved device names (nul,com1, …), names ending in a dot or
space, the reserved leavesdata,extensions,dataprotection,cache,backups, and any
character other than letters, digits,_and-.remove,start,stopandrestartstill
accept an existing name, so earlier installs stay controllable. -
Fresh installs use a new per-instance data directory. It is now tagged by installer kind
(…\Zenvara\service-<name>\datavs…\Zenvara\site-<name>\data; on Linux the sibling
/var/lib/zenvara-service-<name>), so a stock service and a stock IIS site no longer share one
directory and each other's secrets. Existing installs do not move — their directory is pinned
inappsettings.user.yaml. A fresh install on a host that still has the old unpinned directory
with content is refused and told to pass--data-direxplicitly. -
zen app fetchrefuses a running install. Usezen app updateto replace a live install;
fetchinto an empty directory or a first install is unchanged. -
zen migrate-user-idsis gone from the CLI's server command surface, matching the server.
New
zen entity list|get|create|update|delete <type> …— typed one-shot verbs over the server's
platform entities, for scripts. One JSON object on stdout;update/deleterequire--if-match;
create/update --content-fileread back and compare bytes. Distinct exit codes for usage (2),
not-found (4), stale version (5) and could-not-judge (6).zen flow run <name> [--param k=v]… [--params-file f.json]runs a flow and waits for it,
printing{"flow","runId","status","output"}with exit codes that separate a completed run, a
refused one (ok: false), a failed one and an unknown outcome. Keep secret parameters in a mode-0600
--params-file, never in--param.zen whoamiprints the identity the resolved key authenticates as.zen diagnostics versionreads the deployed backend/frontend revisions of an instance.ZEN_REQUIRE_EXPLICIT_HOST=1makes the scripting verbs refuse to fall back to a saved login or
local credentials:--hostis required and the key may only come fromZEN_API_KEY.zen build --property Name=Value(-p, repeatable) passes MSBuild properties through to
dotnet publish.
Safer updates, rollbacks and IIS installs
zen app update/rollbackno longer break an IIS install. They find the host (IIS app pools
or the service) before downloading, stop it, wait forZenvara.App.exeto be released, replace by
move-aside, and roll back on any failure (exit 76, install unchanged).zen app rollbackrefuses a snapshot that is not the predecessor of what is running.zen iis installsets a 100 MB request limit and disables overlapped recycles, backs up a
differingweb.config, clears (and warns about) a read-onlyweb.config, names the failing step
and path on error, and rolls its own changes back.zen iis remove/ reinstall stop pools and sites gracefully and change nothing on a no-op.zen service removerevokes the service'sSeServiceLogonRightinstead of leaving it behind.- Windows elevation relays the elevated process's output to your terminal and pins
--diras
an absolute path across the UAC boundary.
Hardening and fixes
Non-ASCII now survives a non-UTF-8 console (MCP bridge stdio, detached update/rollback scripts,
stdin passwords); generated Windows scripts no longer mis-parse or misread IIS enum attributes;
zen mcp add refuses cmd metacharacters to npm batch shims; data-directory scans are depth-bounded
and do not follow reparse points; a second Linux instance can no longer chown the first one's data.
On the release side, every workflow action is sha-pinned and a red tree can no longer mint a
release.
Supported platforms
| Platform | Archive |
|---|---|
| Linux x64 | zen-linux-x64.tar.gz |
| Linux arm64 | zen-linux-arm64.tar.gz |
| Windows x64 | zen-win-x64.zip |
| macOS x64 (Intel) | zen-osx-x64.tar.gz |
| macOS arm64 (Apple silicon) | zen-osx-arm64.tar.gz |
Each archive contains the single zen executable, with a .sha256 per archive and a signed
SHA256SUMS manifest (SHA256SUMS.jws).
Upgrading from 1.1.0
zen cli update # updates the CLI itselfThen check any script that passes --service-password, passes a changing --data-dir without
--force, relies on a shared --data-dir, installs under a name containing ., or runs
zen app fetch over a live install.