Upgrading
OpaqueVault is pre-1.0. Breaking changes land on minor versions and are always called out in the CHANGELOG. This page condenses each one into what breaks and what to do about it.
To upgrade the binary itself: brew upgrade ov on macOS, or re-run the installer on Linux (curl -fsSL https://get.opaquevault.com | sh). See Updating.
v0.11.2 — ov auth derive-machine-key --app removed
Section titled “v0.11.2 — ov auth derive-machine-key --app removed”What breaks: any script or runbook that calls ov auth derive-machine-key --app <slug>. The flag returns a deprecation error in v0.11.2 and is hard-removed in v0.12.0.
Why: the --app-scoped derivation never worked correctly — it re-keyed the vault session onto a divergent HMAC namespace, so cross-namespace reads and writes 404’d. The machine key was always master-KEK-equivalent on the only path that worked. --app on ov run and ov agent start is unchanged — those are routing flags, not key-scoping.
Fix — regenerate without the flag:
ov auth derive-machine-key --out /path/to/machine.kekRecovering orphaned secrets. If you ever wrote secrets using an --app-scoped machine key, those rows landed under a divergent key and are invisible to your normal master-password session (cross-key operations never completed, so only same-key writes left rows behind). To recover the plaintext:
- Do this on a quiescent host — no untrusted co-tenant workloads while secrets are in a subprocess environment.
- Use the old
--app-scoped key one last time to read each value out:Terminal window ov run --machine-key /path/to/old-scoped.kek --app X --secrets FOO -- printenv FOO - Re-store each value normally (interactive
ov secret set, under your regular session). - Delete the old key file.
The orphaned rows themselves can’t be deleted client-side in this release — they’re unreachable from both the machine-key path (ov secret delete doesn’t accept --machine-key) and the master-password path (different HMAC namespace). They’re encrypted under a key you’ve now discarded, so they’re inert — but if you want them purged from storage, file a support ticket referencing OV-273.
v0.11.0 — OV_STRICT_CONTEXT defaults to ON
Section titled “v0.11.0 — OV_STRICT_CONTEXT defaults to ON”What breaks: non-Claude MCP clients (or custom agents) that call vault_run in “ambient” mode — without declaring which app/env they expect to be operating on. With strict context on, vault_run requires expected_app and expected_env parameters and refuses the call when they don’t match the bridge’s resolved context.
Fix, in order of preference:
- Declare intent. Have the agent pass
expected_app/expected_envon everyvault_run, and use thevault_check_contexttool as a preflight after any directory change (side-effect-free except acontext_forgedaudit event on mismatch). This is the designed flow — it’s what stops acdinto the wrong repo from injecting production secrets. - Opt out (not recommended): set
OV_STRICT_CONTEXT=falsein the environment ofov mcp serveto restore permissive ambient mode. Unset, empty, and unparseable values all resolve to ON.
Also in this release:
- Sessions now expire after
OV_SESSION_TTL(default 1 hour) — stricter than the previous effective 8-hour max lifetime. If your agent sessions start locking mid-day (SESSION_LOCKED), setOV_SESSION_TTL(max24h) in the agent’s environment. See Troubleshooting. - Self-hosted operators: migration
000020_audit_event_idis mandatory — runmake migrate-upafter upgrading the API server. - v0.10.2 was documented but never tagged; upgrading from v0.10.1 delivers both the v0.10.2 changes (including the strict-context flip and
vault_check_context) and the v0.11.0 additions at once.
.ov.yaml v1 to v2
Section titled “.ov.yaml v1 to v2”What changed: the v2 schema pins your project to the app’s immutable UUID via an app_id field (and optionally env_id), instead of relying on the mutable slug alone. v1 files (slug-only, no app_id) have been deprecated since v0.9.6.
What breaks: the MCP bridge refuses legacy v1 files — MCP tool calls in that project won’t resolve your app. The CLI still accepts v1 for now, printing a warning on every invocation.
Fix — one command in the project directory:
ov app pinov app pin takes no arguments — it reads the slug from the .ov.yaml’s existing app: field, resolves it to its UUID on the server, and writes the file to v2 in place. It’s fail-closed: if the file already has an app_id that disagrees with the slug lookup, it refuses to overwrite rather than silently repoint your project.
Don’t confuse it with ov app use — that sets your global config default app in ~/.config/ov/config.toml and never touches .ov.yaml.
Verify the result:
ov status --explainA clean trace shows .ov.yaml matching with an app_id, and no legacy-ovyaml warning.
Related
Section titled “Related”- CHANGELOG — the full, canonical change record
- Troubleshooting — symptom-first fixes
- Machine keys — current machine-key security model
- .ov.yaml — project config reference