`write_policy` called `vaultrs::sys::policy::set`, which targets
`sys/policy/<name>` — the deprecated alias the store gates as a path of
its own. Every grant in this tree names `sys/policies/acl/hive-*`, so a
correctly-scoped controller was refused with a 403 and no hive read
policy has ever been written, on any deployment. The doc comment three
lines above the call already named the modern path; the code is what
moves to meet it.
vaultrs has no endpoint for that path (`grep policies/acl` over 0.8.0:
zero hits, against 8 for `sys/policy`), so this defines one over its own
endpoint machinery — which keeps the client's token header and `/v1`
prefix middleware rather than re-deriving them.
The alternative was to widen the grant to cover the legacy path. This
way needs no policy change at all: the deployed grant already permits
the write, so no store is re-bootstrapped and nothing is entrenched on
an alias upstream has deprecated.
Two tests pin the path and the body shape. The reason this survived
deployment is that nothing in the tree ever asserted either one.
Closes#4177.
mara ruled (a) on #3726: a thin workspace crate over `vaultrs` rather than
keeping bao access in nix and having each end trigger units. The HTTP is the
SDK's job; what this crate owns is the things the controller and a hive must
say *identically*, and which have no other home because neither end is senior
to the other.
Three such agreements:
`path::matrix_account` builds where a credential lives. It is fallible rather
than a `format!`, because both names reach it from elsewhere -- the agent name
from the topology, the account name from an agent's own config -- and a `/` or
`..` in either does not produce a malformed path, it produces a valid path to
a *different agent's* secret. The charset mirrors the KV bucket-name rule.
`Credential`'s `value` field is not a free choice: glue-matrix-bao-token.nix
reads the store with `bao kv get -field=value`, so the name is load-bearing
for a consumer no Rust test can reach. A test pins the serialised shape.
`client::Settings` reads BAO_ADDR / BAO_CLIENT_CERT / BAO_CLIENT_KEY /
BAO_CACERT explicitly instead of letting vaultrs fall through to its own
defaults, which look for VAULT_ADDR / VAULT_CLIENT_CERT / VAULT_CLIENT_KEY.
Every unit in this tree sets the BAO_ spellings, so the defaults would yield a
client with no identity at all -- surfacing as a TLS handshake failure, which
names neither the missing variable nor the reason.
The env read is split from the connect so every misconfiguration arm is
testable without a reachable store and without touching process-global env.
Dependency impact, measured against the lock at forge/main rather than assumed:
native-tls 0 -> 0, openssl-sys 0 -> 0, one reqwest (0.13.4) which vaultrs
shares, and 10 new crates that are all derive/proc-macro helpers.
Refs #3726