ENCLAVR DOCS

Move the namespace writer

Move namespace-writing responsibility by preparing the destination, transferring the approved writer custody, changing the authoritative designation from the current writer, and verifying the new writer before retiring the old copy. Coordinate the handover as one attended operation.

This guide covers an existing, reachable writer and an already enrolled target in the same namespace and initialized OpenBao cluster. It does not move OpenBao leadership, Raft data, DNS authority, DNS publication or certificate storage. Those roles have separate owners and acceptance procedures.

The required isolated OpenBao management endpoint and its private DNS must follow the writer. namespace web starts the implemented temporary endpoint on the current writer and refuses missing private-network or DNS prerequisites. The custody/designation edit alone does not provision those prerequisites. Complete the separate isolation, routing and old-endpoint retirement checks before reporting a successful management-endpoint handover.

Understand the handover boundary

Enclavr currently has no dedicated atomic writer-transfer command. The supported designation change is an explicit edit to the complete assets document by the currently designated writer. The CLI editor verifies the current machine's hostname, selects an accepted writer connection, checks item-update capability, validates the edited document, asks for confirmation, and verifies the write.

That edit does not transport credentials, rebind a host-bound connection, update an AppRole's server restrictions, revoke existing tokens, move issuance checkpoints or provide automatic rollback. Ordinary access-management forms protect the current writer's identity and custody fields; changing scoped permissions there is not a writer-transfer workflow.

State Required outcome
namespace_writer_host Exactly one declared host, matching the new writer's actual hostname.
Existing writer entry in openbao_roles.roles Accurate owner, target host and literal protected connection path; the approved identity and scope remain intact.
Writer connection Accepted for the same namespace and cluster, usable from the destination, with the required existing update scope.
Each host's normal runtime connection Its own accepted consumer connection remains the runtime source.
Private OpenBao management endpoint Declare the new writer's isolated placement, publish/adopt its private DNS and start it with namespace web; verify the old endpoint stops.
Old writer custody Retained under operator control until acceptance, then retired from operational use.

The hostname check is an Enclavr application boundary. Changing it does not invalidate an OpenBao credential or token held elsewhere.

1. Discover and record the current state

On an accepted member, from its repository root, run:

./enclavr namespace status

Record the current writer, its declared role and scope, the exact custody path, the destination's exact inventory hostname, and the existing cluster identity. Use role declarations rather than searching for credential files. A denied lookup does not establish that a role or connection is missing.

Record the intended destination account and the accepted writer connection's exact destination path. The initial provisioning convention is:

${XDG_STATE_HOME:-$HOME/.local/state}/enclavr-openbao-writer/connection.json

An existing accepted connection may use another protected path. Normal writes use the role registry's literal connection_file; they do not derive a path from the caller's home or try the provisioning convention as a fallback. In the assets role registry, connection_file must be a clean absolute path, without shell variables or ~. Keep only non-secret names, paths, approvals and verification results in the handover record.

If namespace_writer_host is not yet established, establish the first writer on the host already holding the accepted connection before planning a transfer. If the current writer is unavailable, use an explicitly planned recovery procedure; the destination cannot appoint itself through ordinary priv edit.

2. Prepare the destination and recovery path

See Prepare and enroll a host and OpenBao operations for those separate prerequisites.

Private management endpoint prerequisite

The required https://openbao.<namespace>/ui/ endpoint belongs on the declared writer, using a dedicated private virtual interface/address, network namespace, container workload and network. Its private port 443 uses the existing OpenBao TLS identity and CA. It must remain separate from public ingress: no caddy-mask-proxy route, shared listener or public application network, AWS Global Accelerator forwarding, wildcard host binding, Let's Encrypt certificate or Tailscale Service. Ordinary tailnet routing to the isolated endpoint is allowed.

Prepare and verify the destination's declared hosts[].openbao_web network, private route and isolation before the designation cutover. The start command does not create networks, routes or access grants. Do not replace missing prerequisites with a public proxy route. Plan the corresponding private DNS update and old-endpoint retirement while preserving existing scoped consumer/API access. See OpenBao browser access for the supported startup workflow; certificate export alone does not provide this endpoint or its relocation.

3. Stage the approved writer custody

Use an authenticated, host-key-verified transfer to the exact destination account, or reuse an already accepted destination copy when its identity and contents match the approved handover. Keep the directory 0700 and the connection a regular 0600 file under parents not writable by other accounts. Check for conflicting files and symlinks before installation; never overwrite a different connection. An identical staged file is a successful no-op.

This is a controlled handover of the approved writer identity, not a source for other hosts' consumer credentials. Preserve the existing namespace, cluster ID, CA, endpoint set, RoleID/SecretID and approved item scope. Keep credentials out of argv, Git, Docker build contexts, logs and transcripts. Do not change either host's runtime .env to select the writer connection.

Inventory writer-owned enrollment/issuance checkpoints and automation separately. The designation change does not relocate them. Transfer only custody explicitly included in the approved operation, preserving checkpoints and their bindings. DNS publisher/observer connections remain at their declared owners unless a separate move has been approved. Recovery shares and CA signing keys remain operator-owned and are not bundled with a routine writer connection transfer.

4. Change the designation from the current writer

On the current writer, use the attended CLI editor:

./enclavr priv edit --namespace '<namespace>' --component assets

Replace <namespace> with the selected namespace. This command opens the protected component in Vim; it is a CLI workflow. In one complete assets edit:

  1. Set namespace_writer_host to the destination's exact declared hostname.
  2. Update the existing writer role's owner_host, identity.hostname and connection_file to the verified destination custody. These declarations must describe already accepted identity state; they do not reissue or rebind a credential. Preserve the role's identity name, enabled/write state, core grants and every other approved permission.
  3. Preserve unrelated hosts, services, roles and DNS-publication declarations.

Review the complete validated change and confirm publication. Do not edit a partial host projection or create a second writer-role entry. Saving Vim alone does not publish; the CLI requires its subsequent confirmation and checks for concurrent version/fingerprint changes. Inspect read-back before continuing and keep complete repository assets mirrors aligned with the accepted document.

After this write, the destination is the designated writer. The old host's normal namespace-write workflows must refuse further edits, even while its protected connection still exists. Do not rely on a previously opened editor as a way around that boundary.

5. Verify the new writer

On the new writer, run:

./enclavr namespace status
./enclavr priv edit --namespace '<namespace>' --component assets

Confirm status shows the new owner, target and custody path consistently. The editor must open through the existing accepted writer and its capability checks. Exit without changes first; this should make no namespace write. It proves the edit preflight, not a completed update.

Complete a planned, meaningful write to an existing item and verify read-back. Use a pre-agreed existing-item metadata correction, such as completing the writer's custody description. If already correct with verified write evidence, preserve the no-op rather than introduce a dummy edit solely to test permissions. Repeat the unchanged operation and confirm no extra item version.

The assets change does not invalidate an unchanged Caddy publication. If the Caddyfile itself changed, use the new writer's TUI preparation and publication forms described in Caddy publication troubleshooting, then deploy and verify affected serving hosts. Keep DNS publishing with its existing owner; verify any affected consumer through its normal workflow. A writer move alone does not require restarting OpenBao or every host service.

After publishing and adopting the current DNS placement, run the CLI command ./enclavr namespace web --yes to start the endpoint on the new writer. Repeated starts retain the original four-hour deadline. The old supervisor detects changed writer ownership or a lost lease and stops; verify this on the old host. Verify that private DNS resolves to the new writer's isolated endpoint, that an authorized private client can reach it with the existing OpenBao TLS identity, and that public ingress cannot receive or forward those requests. Verify existing scoped API consumers still work. Record failed endpoint checks as incomplete acceptance; a successful namespace write or Caddy publication does not prove these network checks.

On the old writer, run ./enclavr namespace status and confirm that it sees the new designation. A fresh attempted priv edit --component assets must be refused as a non-writer before opening an editor or performing a namespace write.

6. Retire old operational custody

After successful read-back, publication and affected-consumer acceptance, remove the old operational writer connection and any transfer staging copies. Retain only approved operator backups outside routine runtime discovery. End old writer and administrator sessions and revoke their session tokens through their normal logout procedure. Preserve the old host's own consumer connection and enrollment.

Retire the old private management endpoint and its obsolete private DNS placement after the new endpoint passes acceptance. Keep the independent DNS authority, publisher and existing scoped API access intact. Endpoint retirement must not be inferred from deleting the writer connection file.

If the same AppRole/SecretID was moved, do not delete that AppRole, its policy or the shared SecretID as old-host cleanup: the new writer still uses them. Retiring a local file is not server-side revocation. Suspected credential exposure needs an explicitly approved rotation with renewed acceptance.

Record the completed owner/custody change, successful write and read-back, unchanged repeat, old-host refusal, publication/consumer verification, and retirement of old operational copies. Repeating an already completed handover should only verify this state, without creating credentials or writing another assets version.

Interrupted handover and rollback

Failure point Recovery action
Before the designation is published Keep the existing writer authoritative. Resolve staging/access conflicts or remove only this attempt's destination staging files.
Required private endpoint is unavailable or not isolated Keep the current ownership while the declared endpoint prerequisites and routing are completed; do not route management traffic through public ingress.
Assets publication reports a conflict Read current authoritative state and prepare a fresh reviewed edit on the current writer. Do not force old version numbers.
Publication response is uncertain Read namespace status and authoritative assets before retrying. Establish which host is now designated; do not assume failure means no write occurred.
New writer works, but the move must be reversed Verify old custody is still usable, then use the new writer to restore the old designation and matching role metadata. Verify the restored writer before retiring the abandoned destination copy. Unchanged Caddy publications remain valid.
Designation changed but the new writer cannot authenticate/write Keep both hosts' protected evidence and stop ordinary mutation attempts. The old host is now refused too. Use the prearranged, authorized administrator/recovery path against the same cluster to restore consistent ownership; retaining the old file alone is not rollback.
Caddy reports stale source versions after handover Update the checkout and relaunch Enclavr; this retired check belongs to an older build. Current code accepts unchanged published Caddyfiles across asset edits and writer moves.

Never create a replacement namespace, reset cluster identity, change the seal/CA, disable writer checks or broaden a consumer's permissions to force completion. Resolve the specific failed prerequisite and retry from observed state.

For the underlying edit behavior, see Edit private data safely.