zebflow 0.11.14

Reactive web automation platform — pipelines, templates, and real-time collaboration in a single binary.
Documentation
# Deployment

The same Zebflow executable can run in three roles.

- **Standalone** runs the controller and office in one process.
- **Controller** handles platform control and coordination.
- **Office** runs projects and project owned services.

Start with standalone unless you need projects to run on separate workers.
`zebflow` (or `zeb`) starts standalone; `zebflow controller` and
`zebflow office` start the cluster roles (`master` and `worker` are deprecated
spellings). A controller or office needs its cluster variables and refuses to
start naming any that are missing:

| Variable | Role | Meaning |
|---|---|---|
| `ZEBFLOW_CLUSTER_MASTER_URL` | office | the controller's base URL |
| `ZEBFLOW_CLUSTER_JOIN_TOKEN` | office, first join only | `zfjoin2:<office_id>:<verify_key>:<secret>`, minted on the controller (`POST /api/platform/cluster/join-tokens`); stored afterwards at `<data-dir>/platform/office-join-token` |
| `ZEBFLOW_CLUSTER_ADVERTISE_URL` | both | the URL this node advertises (default: its own listen URL) |
| `ZEBFLOW_CLUSTER_NODE_ID` / `_NODE_LABEL` | both | stable id and label (default: the role name) |

How offices join, vouch and leave: help topic `guide/federated-offices`.

## Durable Data

Set `ZEBFLOW_PLATFORM_DATA_DIR` or mount `/var/lib/zebflow/data` in the container.
Without durable storage, projects disappear with the container or temporary
machine.

## Network

Use a reverse proxy for TLS and public routing. Send project execution routes to
the office that owns the project. Proxy WebSocket routes with upgrade support.
Long jobs should return a job identity and continue outside a short public HTTP
request.

## Health

The main application uses port `10610` by default. A separate health listener
can use `ZEBFLOW_HEALTH_PORT`, commonly `10611`. Use the separate listener for
liveness so a busy application route does not hide whether the process is
alive. Use readiness to decide whether the office should receive traffic.

## Before Production

- use a strong admin password
- keep the data root on durable storage
- back up projects and databases
- set CPU and memory requests based on measured work
- limit upload size at every proxy and at Zebflow
- use explicit outbound network rules
- set log retention
- test restore before relying on backup

## Offline maintenance

These run against a data directory with no server, for the day the server
will not start (stop it first — they refuse to run beside a live instance):

```
zebflow project config migrate <owner> <project>     repo/zebflow.json → repo/zebflow.yaml
zebflow project lock migrate <owner> <project>       pre-v1 zeb.lock format
zebflow project pipelines migrate <owner> <project>  persisted pipeline ids → source-relative form
zebflow admin reset-password <owner>                 rotate to a fresh random password, printed once; the next login must choose a new one
zebflow admin break-glass [<owner>]                  re-enable local login on a joined office (recorded, reported to the controller later)
zebflow admin detach                                 leave the controller; the office keeps everything it has
```

Kubernetes manifests for a cluster are generated by `zeb k8s cluster …`; the
Helm chart is under `charts/zebflow`.