Secrets
Plain credentials never appear in flow YAML, environment YAML, or connection YAML. They are referenced as ${secret:path} (whole-value) or ${secret:path:key} (sub-key form, useful when one secret entry has multiple fields like host/username/password).
# In a connection fileHost: "${secret:sftp/partner:host}"UserName: "${secret:sftp/partner:username}"Password: "${secret:sftp/partner:password}"Resolution timing
Section titled “Resolution timing”Secrets are resolved at flow start in a single async batch. A flow that fails secret resolution fails before any operator runs — there is no half-failed state where one step ran with a real credential and a later step crashed on a missing one. There is also no mid-flight credential swap: a running flow continues with the values it resolved at start.
Adding or rotating a secret
Section titled “Adding or rotating a secret”Three surfaces, same primitives:
# CLI — one secret at a timezen secrets set prod/db connection-string="Server=prod-db;Database=warehouse;…"# RESTcurl -X POST http://localhost:5000/api/v1/platform/entities/secret \ -H "Authorization: Bearer $TOKEN" \ -d '{"path":"prod/db","value":{"connection-string":"…"}}'# MCP — Claude Code, VS Code, or any MCP clientTool: set-secret args: { Path: "prod/db", Value: { ... } }Rotation is a re-set: write the new value to the same path. The change takes effect for any invocation that starts after the write.
Storage backends
Section titled “Storage backends”Two providers:
- Encrypted file — AES-256-GCM with a 256-bit key, single-host. The encryption key comes from one of three sources: a direct base64 key, a file path, or a PBKDF2 password (100,000 SHA-256 iterations). The file lives at
auth/secrets.encand is never git-tracked (**/*.encis a hardcoded exclude). - HashiCorp Vault — for multi-host and centralised secret management.
Secrets do not travel through git config sync — replicate them out-of-band (a shared Vault, or a copied secret blob + key).
The declarative credentials block
Section titled “The declarative credentials block”The modern form ties a connection to a secret declaratively. A credentials: block names a multi-key serviceAccount: secret plus a fields: map of yamlField → blobKey:
type: zenvara/sftpcredentials: serviceAccount: sftp/partner fields: Host: host UserName: username Password: passwordPer-user credentials override the service-account default when personal/<owner>/<connection> is set — <owner> is the underlying user id. Global API keys, triggers, cron, and queue invocations silently use the service account by construction.
Secrets policies
Section titled “Secrets policies”A policy says “flows tagged X may read paths matching Y” — this is what stops a careless author from referencing production credentials in a dev pipeline. The policy file (auth/secrets-policy.yaml) is configured by an administrator; flow authors interact with it through tags.
Tags live on a sibling annotation keyed by entity, not in the flow YAML — they are governance metadata, not pipeline logic. Add one with add-tag (MCP/REST): entityType: flow, entityId: my-flow, tag: production. The policy engine reads the annotation at flow-start. Path-based access rules are separate from user roles, so a dev flow cannot reach prod secrets even if the invoking user is an admin.