# 60 -- Vault VIP: proposed values, derivation, and confirm-before-write gates

Operator, 2026-07-25: "Give me a recommendation I can relay to Code." This is it.

NOT paste-ready configuration. Hard rule 2 is in force: never use an inferred value in
a command. Every address below is DERIVED from a point-in-time snapshot plus a ratified
decision. Code CONFIRMS each against live state before writing. If a value cannot be
confirmed, stop and report -- do not write it.

This is a D-020 CONFORMANCE REPAIR, not a new decision. Per GA-R3 it is OPS: a
changelog item plus a values change, no D-number. Doubt resolved down.

Verified against repo HEAD bc9a2df.

================================================================================
## Why vault needs this
================================================================================

Measured (`git grep` across the tracked tree excluding `docs/archive`): NO `vip:` for
vault anywhere. `bundle.yaml`'s vault stanza has no `options` block at all.
`overlays/dc-ha-scaleup.yaml` sets `vault: {num_units: 3, to: [lxd:0, lxd:1, lxd:2]}`,
declares `vault-hacluster` with `cluster_count: 3`, and re-adds
`[vault:ha, vault-hacluster:ha]`.

hacluster manages a VIP resource in pacemaker. With no `vip` on the principal there is
no VIP resource to manage, so `vault:secrets` consumers resolve to a unit address rather
than a virtual one. The exact consumer-side behaviour is charm-specific and is NOT
asserted here -- it belongs in the VERIFY-LIVE set below.

Tenant-facing consequence: `barbican-vault` is a `vault:secrets` consumer, and barbican
is tenant-facing -- tenant secrets, plus the TLS material Octavia uses for terminated
listeners. Losing one vault unit degrades tenant secret operations and TLS load
balancers on a cloud sold on HA. D-020 lists vault among the applications carrying
provider+metal VIPs; the artifact departs from it with no decision recording the
departure.

================================================================================
## Proposed shape
================================================================================

PLANES: metal-admin + metal-internal ONLY. NO provider leg.

  Vault has no external consumers. D-067 puts `barbican-vault -> vault` (vault-kv) on
  metal-internal. A provider VIP would expose the cloud's TLS root beyond need for zero
  benefit. Both planes are already bound in vault's stanza (`""` -> metal-admin;
  `access`, `certificates`, `cluster`, `external`, `ha`, `secrets`, `shared-db` ->
  metal-internal), so the VIP lands on bound spaces.

  Tenants receive the Vault root CA as a FILE in the handoff packet, not as network
  reachability, so omitting the provider leg does not affect tenant handoff.

OCTET: `.61`. A RECOMMENDATION, NOT A DERIVATION. It is next after the band in
`overlays/vr1-dc1-vips.yaml`: keystone `.50`, barbican `.51`, cinder `.52`, glance
`.53`, magnum `.54`, neutron-api `.55`, nova-cloud-controller `.56`, octavia `.57`,
openstack-dashboard `.58`, placement `.59`, ceph-radosgw `.60`.

ARTIFACT: per ruling 3 these land in the per-DC VIP overlays
(`overlays/vr1-dc0-vips.yaml`, `overlays/vr1-dc1-vips.yaml`), never in `bundle.yaml`.

================================================================================
## Proposed values
================================================================================

v4 bands: `netbox/draft/vr1-office1-current-20260725.json`, six-plane prefixes by
`scope_site`. v6 bands: same snapshot plus the D-111 subcarve (metal `/60` at `:20`,
admin `/64` `:20`, internal `/64` `:21`).

  DC0 (site vr1-dc0)
    metal-admin        10.12.8.0/22        -> 10.12.8.61
    metal-internal     10.12.12.0/22       -> 10.12.12.61
    metal-admin v6     fd50:840e:74e2:220::/64  -> fd50:840e:74e2:220::61
    metal-internal v6  fd50:840e:74e2:221::/64  -> fd50:840e:74e2:221::61

  DC1 (site vr1-dc1)
    metal-admin        10.12.68.0/22       -> 10.12.68.61
    metal-internal     10.12.72.0/22       -> 10.12.72.61
    metal-admin v6     fd50:840e:74e2:320::/64  -> fd50:840e:74e2:320::61
    metal-internal v6  fd50:840e:74e2:321::/64  -> fd50:840e:74e2:321::61

Vault takes NO GUA leg, so it never touches the D-111 API-VIP `/64` at `:11`.

================================================================================
## CONFIRM BEFORE WRITE -- four gates, not suggestions
================================================================================

1. `.61` is unallocated in all four v4 plane bands above and in the four v6 `/64`s. The
   snapshot is point-in-time; re-read live.

2. NO MAAS deployed-node band claims the VIP octet on the metal planes. **Largely
   answered by decision, 2026-07-25:** D-134 as AMENDED (the authoritative contiguous
   table -- NOT the superseded original above it) reserves `.50-.99` as the VIP band on
   row 0 of every VR1 DC plane `/22`, with nodes at `.100-.200` and dynamic/enlistment at
   `.201-.254`. `.61` therefore sits inside the reserved VIP band with no node or dynamic
   range anywhere near it, and CURRENT-STATE records the dynamic-range move to `.201-.254`
   as in place. What remains is the narrow check: confirm `.61` is not already assigned.
   The v6 side is unaffected -- D-111's VIP-dedicated `/64` at `:11` exists only on the
   provider/GUA leg, and vault takes no GUA leg.
   IF `.61` IS TAKEN: the next free octet inside `.50-.99` is the answer, not a band
   change. A band change would be a D-134 amendment and an operator ruling.

3. The vault charm on `1.8/stable` (pinned; D-068 keeps the 1.16 lineage ruled out)
   accepts a space-separated dual-family `vip` value. Do not assume -- confirm against
   the charm's config schema. If it does not, the fallback is single-family plus a
   recorded D-101 exception, which is an operator ruling.

4. After the change, confirm the VIP is OWNED by a unit, not merely configured.
   `scripts/cloud-assert.sh` currently false-passes this per
   `docs/audit/stage5-expansion-review-20260724.md`; the per-hacluster VIP-owned check
   proposed in D-NNN is what closes it. Until it exists, verify by hand.

================================================================================
## A HARD GATE COUPLING -- do not miss this
================================================================================

`scripts/lib-net.sh:59` sets `VIP_COUNT_EXPECT=11`. It is consumed by
`scripts/pre-flight-checks.sh` at :79 (warn on vip line count) and at :99-102, where a
count mismatch is a **fail**, not a warn.

Adding vault's VIP takes the real count to 12. `VIP_COUNT_EXPECT` must move to 12 in the
SAME change, or the gate fails on a correct configuration.

Caveat: CURRENT-STATE flags `pre-flight-checks.sh` as VR0-frozen (no `$DC` selector,
host_sysid-by-hostname), so whether it gates VR1 today needs confirming. Either way the
constant lives in the shared library and any DC-aware successor inherits it. D-134's band
table also quotes `VIP_COUNT_EXPECT=11` in prose, so that reference goes stale in the same
moment -- point it at the library rather than restating the number.

Longer term: a generator emitting the VIP set should DERIVE this count, not carry it as a
second literal that has to be remembered.
