Git-backed Versioning
With Git versioning on, every connection / environment / flow / template / secret-reference change is committed to a local git repository and (optionally) pushed to a remote. You get an audit trail, one-call config rollback, and branch-based staging.
Step 1 — Pick a LocalPath
Section titled “Step 1 — Pick a LocalPath”The working tree where commits are written. Three hard requirements, each enforced at startup:
- Owned by the service user. libgit2 refuses a working tree owned by a different OS user (its
safe.directoryequivalent). Running aszenvara, the repo must be owned byzenvara. - Writable under systemd hardening. With
ProtectSystem=strict, the path must sit under aReadWritePathsentry. The data dir (/var/lib/zenvara) already qualifies. - Outside
Storage.Directory. A nested path logs an overlap warning — keep it in a sibling directory.
install -d -o zenvara -g zenvara /var/lib/zenvara-versions
[Service]ReadWritePaths=/var/lib/zenvara-versions# then: systemctl daemon-reloadStep 2 — Use a token, not a password
Section titled “Step 2 — Use a token, not a password”libgit2 push/clone with an interactive account password trips server-side bot protection (e.g. Bitbucket’s CAPTCHA lockout) and will lock the account. Create an HTTP access token or a dedicated service account with repository write, and put those in Remote.Username / Remote.Password. Leave Remote.Url empty for local-only versioning.
Step 3 — Seed the repository before first start
Section titled “Step 3 — Seed the repository before first start”Pre-create the working tree so the platform simply opens it:
cd /var/lib/zenvara-versionssudo -u zenvara git init -b main .sudo -u zenvara git -c user.email=ops@example.com -c user.name=Zenvara \ commit --allow-empty -m "Initialize git-backed config versioning"sudo -u zenvara git remote add origin https://git.example.com/scm/team/zenvara-config.gitIf the remote already has a main branch with history, skip the manual init — the platform clones it on first start.
Step 4 — Configure and restart
Section titled “Step 4 — Configure and restart”Git: Enabled: true LocalPath: "/var/lib/zenvara-versions" # owned by service user, outside Storage.Directory ProductionBranch: main # the branch `live` resolves to BaselineOnEnable: false # best-effort startup storage→git baseline Remote: Url: "https://git.example.com/scm/team/zenvara-config.git" AutoPush: true Username: "zenvara-ci" # service account or token owner Password: "<http-access-token>" # NOT a personal account password CommitIdentity: Name: "Zenvara" Email: "ops@example.com"After systemctl restart zenvara, the log shows Opening existing git config repository at <LocalPath>. Verify end to end by editing any entity: a commit Update entity: <name> appears in the repo and, with AutoPush, lands on the remote.
Branch staging
Section titled “Branch staging”A branch is a staging area for definition changes — edit safely, review the diff, promote. Give it a feature-style name for the change it carries (edi-rework), not a tier name. URLs carry the branch as a path segment: /api/v1/main/flows/... runs the production version, /api/v1/edi-rework/flows/... runs the version staged on the edi-rework branch. On git-disabled installs, the live alias resolves to the production branch so the same URLs work.
The loop is stage → diff → promote:
-
Stage. Point edits at the branch by putting its name in the URL segment (Studio’s branch switcher does this for you). Production URLs keep serving the old definition.
-
Diff. Review what the branch changed before anything ships —
GET /api/v1/platform/branches/edi-rework/diff, the MCP resourcebranches:///edi-rework/diff, or the Studio Branches page. -
Promote. Merge the reviewed changes into production storage as a no-fast-forward merge:
- Studio — the Branches page: select the branch, review, click Promote.
- MCP — the
promote-branchtool ({ "branch": "edi-rework", "preview": true }for a dry run). - REST —
POST /api/v1/platform/branches/promotewith{ "branch": "edi-rework", "preview": true|false }.
Preview is a true dry run; conflicts abort the whole promotion; promotion requires the
flow:promoterelease permission (admin-held by default — distinct from authoring). There is nozenCLI promote verb — promotion is a Studio / MCP / REST action.
Multi-instance config sync
Section titled “Multi-instance config sync”With git versioning plus a shared remote, Git.Sync.Enabled: true makes an instance:
- fetch the remote,
- reverse-sync changed config into storage,
- invalidate caches.
Trigger it via PollInterval and/or the POST /api/v1/platform/git/sync HMAC webhook. The same remote keeps multiple instances in sync, with ConflictPolicy: manual | remote | local.