v1.8.0 — read-only mode, working policy defaults, declared environments
Family release driven by VMware-AIops#31,
where an operator running Llama 3.3 70B (Goose / OpenShift AI, on-prem H100) had to
hand-write 17 prompt guardrails to make tool calling reliable. A prompt is advisory — a
model can ignore it. Every guardrail that could move into the harness has.
Added
- Read-only mode. Set
VMWARE_READ_ONLY=true(orVMWARE_<SKILL>_READ_ONLY, or
read_only: truein config.yaml) and every write tool is removed from the MCP registry
at start-up.list_tools()never offers them, so the model cannot call what it cannot
see. Off by default — nothing changes unless you turn it on. Fail-closed: if the
mode is requested but cannot be guaranteed, the server refuses to start rather than
running open. environment:on each config target, declaring which environment it is
(production / staging / lab). Policy rules scope by this value.
Added — list results now state whether they are complete
Every [READ] list tool returns the family envelope instead of a bare array:
{"items": [...], "returned": 50, "limit": 50, "total": 213,
"truncated": true, "hint": "Showing 50 of 213. Raise limit or narrow the query..."}
This closes the reported failure where long responses were summarised as "no data
returned": a bare list gives a model no way to tell a complete answer from page one, so
it guessed. truncated: false now positively states completeness — including when
items is empty, which means "checked, found none", not "the call failed".
- 4 tool(s) converted across ops, MCP and CLI.
totalis derived from what the code proves rather than from the wire: the client
either drains the cursor or stops at its 1000-item cap, so a fetch under the cap
consumed every page. It is measured before client-side filtering — a filter can shrink
a capped scan below the cap and turn "unknown" into a confident lie. Name-filtered and
capped listings therefore reporttotal: null.
Fixed
- Deleting an empty DFW policy was about to start failing. The pre-delete check read
if list_dfw_rules(...)— truthy for an envelope dict whether or not it holds rows, so
every policy delete would have been refused with "it still contains firewall rule(s)".
Caught while converting; the existing suite only covered the has-rules branch, so the
empty-policy branch is now pinned by its own test.
Changed — migration, read this
-
Approval tiers now actually run. They shipped in v1.6.0 but the engine only ever
read~/.vmware/rules.yaml, and a fresh install has no such file — so every deny rule,
maintenance window and approval tier had been inert on every install that never
hand-authored one. A packaged baseline now loads when you have written no rules of your
own. Writes at medium risk and above are stamped with their tier in the audit log;
irreversible work and guest execution against a target declaredproductionrequire a
named approver viaVMWARE_AUDIT_APPROVED_BY. -
environment:will become required for writes. Today a state-changing operation
against a target that declares none still runs and logs a warning. The next major
release refuses it. Declare it now and that upgrade is a no-op:targets: prod-vc01: host: vc01.corp.local environment: productionRead-only operations are never affected, in this release or the next. Check what applies
to your targets before upgrading:vmware-audit policy --operation vm_delete --env <env>.
Fixed
- Policy glob patterns with a leading wildcard silently matched nothing. A rule written
operations: ["*_delete"]parsed fine, read correctly, and never fired — only a trailing
*was honoured. Now full glob matching, for operations and environments alike. - Config-path overrides (
VMWARE_<SKILL>_CONFIG) are honoured when readingread_only
andenvironment, so a setting in a custom config file is no longer silently ignored.
Notes
- Requires
vmware-policy>=1.8.0; publish that package first. vmware-audit policyreports which rules are in force and where they came from —
including the case where your rules file exists but failed to parse, which previously
looked identical to "policy is working".