maand push

Push a user-owned bucket into an existing maand server bucket:

maand init
# edit workspace/ and templates/
maand build
MAAND_SERVE_TOKEN=... maand push https://maand.example \
  --bucket 6ba7b810-9dad-11d1-80b4-00c04fd430c8

The local data/maand.db is a disposable build artifact. maand build records maand.conf, workspace job files, core workspace configuration, templates, a bundle-format version, and the producing binary's Git hash. Push sends a consistent sanitized SQLite snapshot; local KV, CA keys, and runtime state are not transferred.

Replacement behavior

The target bucket must already exist. Push authoritatively replaces:

It preserves server-owned state:

tmp/ is cleared. Other non-reserved root entries are removed. Arbitrary Git-root files and executable modes are not part of the bundle.

After the filesystem commit, the server runs build against its existing database. Push does not deploy. If extraction fails, the previous source tree is restored. If build fails, the new source remains installed as current while last successful stays pointed at the prior good revision. Inspect the run in Activity, then either fix the user-owned bucket and push again, or roll back:

MAAND_SERVE_TOKEN=... maand push rollback \
  --server https://maand.example \
  --bucket 6ba7b810-9dad-11d1-80b4-00c04fd430c8

If the server process stops mid-push, the next maand server start recovers orphan upload directories and incomplete rollback staging before accepting traffic.

Source revisions

Every accepted push retains an immutable revision keyed by the SHA-256 of the uploaded bundle under .maand/source-revisions/. The server tracks:

Pointer Meaning
current Live source tree after the latest commit
last_successful Latest revision whose server-side build succeeded

List them:

MAAND_SERVE_TOKEN=... maand push revisions \
  --server https://maand.example \
  --bucket 6ba7b810-9dad-11d1-80b4-00c04fd430c8

maand push rollback atomically restores a retained revision (default: last_successful; optional --revision <hash>), rebuilds the server catalog, and writes an audited run. It does not deploy. The server keeps the newest 10 revisions and never prunes current or last_successful.

Ownership and operations

Push and source rollback are the only server APIs that change user-owned source. The UI and remaining API expose source as read-only. They still manage server-owned bucket metadata, SSH private keys, .ssh/known_hosts, catalog/runtime state, and operational actions such as trust, build, deploy, health checks, hooks, job control, snapshots, GC, and init/upgrade.

Worker facts over the server API only reports facts; it cannot generate or update workspace/workers.json. To refresh worker definitions, run local maand worker facts --generate-workers, commit the result, build, and push.

Durable push history

Every accepted push is an asynchronous server run. Its live output appears in Activity, while durable structured history is written to logs/runs/<run-id>/maand.log. The terminal event records the SHA-256 hash of the exact uploaded bundle, producer build hash, bundle version, current and last-successful revision pointers, timestamp, build result, and exit status for success, validation/extraction failure, cancellation, and build failure.

Flags and authentication

Flag / bucket Description
--bucket <uuid> Required existing server bucket
--token / MAAND_SERVE_TOKEN Server bearer token
--totp / MAAND_SERVE_TOTP Optional current TOTP code; the client creates a session before upload
--timeout Total upload and server-build timeout; default 30m

Subcommands revisions and rollback take --server <url> instead of a positional URL. rollback accepts optional --revision <hash>.

TLS certificates use the operating system trust store. Credentials must not be placed in the server URL. The server rejects incompatible schemas or bundle versions, corrupt databases, unsafe paths, excessive entries, oversized payloads, and pushes attempted while that bucket already has an active run (409). Runs on unrelated buckets do not conflict.

Build identity

make build embeds the current Git hash in the binary. maand init and maand build record their binary hashes in the bucket row, and maand info shows the running, initializer, and content-producer hashes. Compatibility is decided by the bundle-format version and structural validation, not by requiring client and server Git hashes to be identical.