# Migration Guide
This guide tracks migration work for the stable `1.0.x` release. The endpoint
matrix now has zero `planned` and zero
`decision` rows; remaining non-typed rows are intentionally documented as raw,
external, partial, gated, or rejected boundaries.
## From `openbao` 1.0.1 To 1.0.2
`1.0.2` is a source-compatible dependency and release-documentation update.
Normal callers should not need code changes.
Notable maintenance changes:
- `base64-ng` is updated to `1.0.8`.
- Semver-compatible transitive dependencies in `Cargo.lock` are refreshed.
- The crates.io README is shorter and focuses on current SDK support instead
of historical pre-`1.0` release milestones.
- The pinned `taiki-e/install-action` CI action is updated to the latest v2
tag checked by the release gate.
## From `openbao` 1.0.0 To 1.0.1
`1.0.1` is a source-compatible patch hardening release. Normal callers should
not need code changes.
Review these behavior changes if you intentionally customized TLS:
- `OpenBaoConfig::min_tls_version(tls::Version::TLS_1_0)` and
`TLS_1_1` now fail when the client is built.
- `OpenBaoConfig::min_tls_version(tls::Version::TLS_1_2)` now fails at build
time unless the crate is compiled with `tls12-acknowledged`; the dedicated
`min_tls_12()` helper was already gated this way.
- `OpenBaoConfig::add_root_certificate()` now preserves root-only trust mode
after `only_root_certificates()` instead of widening trust back to platform
roots. Platform roots are used only while the configuration remains in merge
mode.
No endpoint types, request structs, or response structs changed.
## From `openbao` 0.15 To 1.0
`1.0.0` is source-compatible with normal `0.15.0` application code. It freezes
the public API surface that was trialed in the `0.15.0` stable-candidate line.
Update `Cargo.toml`:
```toml
[dependencies]
openbao = "1"
```
Recommended checks before deploying the stable release:
- run your existing `0.15.0` integration tests with `openbao = "1"`;
- keep feature selections explicit for operator APIs, legacy TLS, RADIUS,
Transit import software wrapping, and test-only HTTP escape hatches;
- review `SECURITY.md` for accepted residuals around transport buffers,
bootstrap locking, and software BYOK wrapping;
- use `docs/API_STABILITY_AUDIT.md` and
`docs/OPENBAO_2_5_ENDPOINT_MATRIX.md` as the stable endpoint-boundary
reference.
## From `openbao` 0.14 To 1.0
`1.0.0` is source-compatible with normal `0.14.0` application code, through the
`0.15.0` stable-candidate additions.
Update `Cargo.toml`:
```toml
[dependencies]
openbao = "1"
```
Adopt these final stable-scope additions where they fit:
- use `Sys::wait_until_unsealed_with_delay` for bounded startup or recovery
polling. Enable `tokio-helpers` only when the direct
`Sys::wait_until_unsealed` Tokio convenience method is useful;
- use `Client::wrapping("5m")?` and `WrappedResponse<T>` when an application
needs OpenBao response wrapping without dropping to untyped JSON. Delivery of
the one-use wrapping token remains caller-owned;
- use `AclPolicyBuilder::allow_path_with_wrapping` or the
`_with_required_wrapping` helper variants to require response wrapping in
path rules. Continue using reviewed `PolicyWriteRequest` documents for
advanced ACL parameter constraints;
- use `AdminBootstrap::ensure_pki_mount`, `ensure_database_mount`, and
`ensure_ssh_mount` for idempotent mount convergence;
- use `AdminBootstrap::ensure_database_role`,
`ensure_database_static_role`, and `ensure_ssh_role` for role convergence
where those engines are already configured;
- keep PKI CA setup, database connection configuration, SSH CA key setup,
request-level seal back-pressure, and KV v1 convergence outside
`AdminBootstrap`. Those remain operator or application-policy workflows.
## From `openbao` 0.8 To 0.9
`0.9.0` remains source-compatible with normal `0.8.0` application code and adds
stabilization helpers that are intended to survive into `1.0.0`.
Update `Cargo.toml`:
```toml
[dependencies]
openbao = "1"
```
Keep these `0.8` patterns:
- use `openbao::SecretString` instead of depending on `secrecy` directly;
- prefer `Client::from_env_with_token()` for deployed services;
- keep TLS verification enabled and add root certificates through
`OpenBaoConfig`;
- use feature gates for operator APIs and Transit byte helpers;
- use `read_optional` or `Error::is_not_found()` for absent secret handling;
- use `Sys::wait_ready_with_delay` for startup polling instead of ad hoc
retry loops.
Adopt these `0.9` additions where they fit:
- use `RetryPolicy`, `RetryableMethod`, and `Client::request_json_with_retry`
only for caller-approved idempotent GET, HEAD, or OpenBao LIST raw JSON
requests. Typed helpers remain single-shot by default so non-idempotent
writes are not retried accidentally;
- keep existing paginated list helper calls. Internally they now share
`ListPageOptions`, which validates the `after` cursor and bounds `limit`.
Token accessors, lease IDs, and other secret-bearing lists intentionally stay
on dedicated helpers;
- use `AdminBootstrap::ensure_pki_role`,
`AdminBootstrap::ensure_identity_entity`, and
`AdminBootstrap::ensure_identity_group` for idempotent service setup. These
compare only fields set in the desired request and do not perform PKI CA
setup or database connection configuration;
- use `docs/API_STABILITY_AUDIT.md` and
`docs/OPENBAO_2_5_ENDPOINT_MATRIX.md` as the pre-`1.0.0` source of truth for
planned, rejected, external, raw, and gated endpoint boundaries;
- read `docs/QUANTUM_READINESS.md` for the crate's advisory-only posture. It
does not claim post-quantum safety for current OpenBao deployments.
## From Earlier `openbao` Releases
### 0.1 To 0.3
- Replace direct URL string assembly with typed helpers such as `client.kv2`,
`client.kv1`, `client.transit`, and `client.sys`.
- Use `try_with_token` for token validation at client construction time.
- Treat Transit plaintext/ciphertext fields as secret material. Do not log
request or response structs unless their `Debug` implementation is known to
redact secret-bearing fields.
### 0.4 To 0.6
- Replace manual environment parsing with `Client::from_env_with_token()`.
- Replace local KV config maps with `Kv2ServiceConfig` helpers when loading
service settings.
- Move byte-oriented Transit glue to the `transit-bytes` feature when raw
bytes are more natural than OpenBao's base64 strings.
- Use `AclPolicyBuilder` and `AdminBootstrap` for common service setup instead
of assembling ACL HCL and mount requests with ad hoc strings.
- Keep production init/unseal/rekey/rotate and destructive PKI root deletion
behind `operator-ops` and `operator-ops-acknowledged`; default builds
intentionally cannot call those APIs.
### 0.7 To 0.8
- Use concrete auth/admin helpers for AppRole, LDAP, RADIUS, Kerberos,
Kubernetes auth, TLS certificate auth, Userpass, and JWT/OIDC instead of raw
JSON calls where supported.
- Use `ListEntries` for ordinary string list responses, but keep token
accessors and other secret-bearing lists in their dedicated types.
- Use `TokenRole`, Transit lifecycle/batch helpers, PKI tidy/status/cancel,
Identity lookup/merge, and lease prefix/count helpers instead of
hand-written endpoint paths.
- Use `Error::is_rate_limited`, `Error::is_temporary`, and
`Error::is_permission_denied` where caller logic branches on common API
failures.
## From `vaultrs`
The `openbao` crate is OpenBao-specific and uses `X-Vault-Token` by default
for documented compatibility while keeping the API centered on OpenBao
deployment behavior.
Common migration steps:
- Replace `vaultrs` client construction with `Client::new`,
`OpenBaoConfig`, or `Client::from_env_with_token`.
- Replace direct token strings with `openbao::SecretString`.
- Replace engine-specific functions with typed handles such as
`client.kv2("secret")?`, `client.transit("transit")?`, and
`client.sys()`.
- Review feature flags. `openbao` keeps risky operator and legacy TLS behavior
behind explicit opt-in features.
- Review error handling. Use `Error::status()`, `Error::is_not_found()`, and
related predicates rather than matching a transport crate directly when
possible.
Do not migrate by disabling TLS verification or reusing root tokens in service
configuration. Use scoped service tokens, AppRole SecretIDs, Kubernetes auth,
or another workload auth method appropriate to the deployment.
## From Bespoke `reqwest` Wrappers
Replace hand-written wrappers in layers:
1. Move address, namespace, CA, and token parsing into `OpenBaoConfig` or
`Client::from_env_with_token`.
2. Replace request URL string concatenation with typed engine handles.
3. Replace raw secret strings with `SecretString` in request and response
structs.
4. Replace logging of raw HTTP errors with sanitized `openbao::Error`
handling.
5. Move custom plugin or unsupported endpoint calls behind a small local typed
wrapper around `Client::request_json`.
6. Add tests that assert documented HTTP method, path, headers, and redaction
behavior for each local wrapper.
For custom plugin wrappers, prefer `PluginMount`, `validate_mount_path`,
`validate_endpoint_path`, `BoundedStringList`, and
`deserialize_bounded_string_vec` instead of local path concatenation or
unbounded list response types.
## Security Checklist
- Never log tokens, token accessors, lease IDs, Transit plaintext/ciphertext,
PKI private keys, raw storage values, AppRole SecretIDs, or OpenBao backup
payloads.
- Do not use loopback HTTP outside fresh local development instances.
- Do not use `bootstrap_dev` for production, shared environments, HSM/KMS
auto-unseal deployments, or any instance requiring an operator ceremony.
- Do not enable `native-tls`, `operator-ops`, `allow-sha1-acknowledged`,
`allow-weak-jitter-fallback-acknowledged`, `radius-auth`,
`radius-auth-acknowledged`, or `insecure-ldap-tls-acknowledged` without
recording the deployment reason.
- Keep response-size limits low for small-response services.
- Prefer least-privilege policies generated by `AclPolicyBuilder` or reviewed
policy strings.