# 20 -- Operator ruling records (GA-R5)

GA-R5: a ruling exists only when its Status line quotes the QUESTION and the operator's
EXACT UTTERANCE, dated, committed and pushed BEFORE dependent work. One decision per
operator exchange -- these three arrived in three separate exchanges on 2026-07-25 and
were not batched at the point of ruling. If recording them in a single commit would
read as a batch adoption, split into one commit per ruling; the safe reading wins.

Chat has NOT adopted anything. These are records for Code to commit.

================================================================================
## RULING 1 -- address family policy (amends nothing; confirms D-101)
================================================================================

QUESTION PUT TO THE OPERATOR: whether dc1 phase-4 deploys v4-only (deferring IPv6, per
the expansion review's option (b)) or dual-stack.

OPERATOR UTTERANCE (2026-07-25), verbatim:
  "Dual stack to be used where IPv4 is required, IPv6 where IPv6 only makes sense."

CLARIFYING EXCHANGE, verbatim: "Dual stack deployment for DC0 and DC1. This is the
deployment when the dual-stack is added"

EFFECT:
- This is D-101's family matrix restated, not a new policy. D-101's own rationale line
  already reads "v6 wherever possible, v4 only where forced". No amendment required.
- The expansion review's option (b) v4-only phasing is CLOSED.
- `overlays/vr1-dc1-vips.yaml` (v4-only triple) is not a D-101-conformant deploy input
  on its own; the reconciliation is forced before deploy.
- Applies to BOTH DC0 and DC1 in this deployment, so the literal burden is both DCs.
- What it does NOT reduce: all three API VIP legs remain dual-stack under D-101
  (provider-public GUA plus v4 for external clients and workload nodes reaching public
  Keystone; metal-admin v4 because PXE is v4-first; metal-internal v4 for D-020's
  `resolve_address(INTERNAL)` path). The six-value-per-app string in
  `overlays/dc-dc-ipv6-family-matrix.yaml` is D-101-correct as authored.
- STILL OPEN under this ruling: octavia. D-101 places `lb-mgmt` in the IPv6-only ULA
  group, but the overlay documents live upstream IPv6 breakage there. That sub-ruling
  is open -- see open question 2 in item 10.

CURRENT-STATE consequence: bullet (b) "v4-only vs dual-stack phasing ... operator
decides" is RESOLVED. See item 30.

================================================================================
## RULING 2 -- keystone policy-override VERIFY-LIVE gate
================================================================================

QUESTION PUT TO THE OPERATOR: whether to add a VERIFY-LIVE gate confirming the
`policyd-override` resource lands on every keystone unit after `dc-ha-scaleup.yaml`
scales keystone to 3, given that a broken override is atomic (the whole policy is
discarded, silently reverting every tenant domain-manager to a plain user).

OPERATOR UTTERANCE (2026-07-25), verbatim:
  "dc-ha-scaleup: Yes to the verify-live"

EFFECT: add to the Stage-4 VERIFY-LIVE set --
  `juju status` shows `PO:` on EVERY keystone unit, never `PO (broken):`.

Rationale for the gate's weight: this is the highest-consequence single check in the
deploy. `bundle.yaml` carries `use-policyd-override: True` with
`resources: {policyd-override: ./policies/overrides.zip}`; `policies/overrides.zip` is
present (3419 bytes, single member `domain-manager-policy.yaml`) and
`scripts/keystone-policy-drift.sh` byte-matches the member against source. The
mechanism is intact at bc9a2df -- the gate confirms it SURVIVES scale-up. Failure has
no other symptom, and it takes down the SCS Domain Manager persona (D-051, D-064) that
the commercial tenant self-service model rests on.

================================================================================
## RULING 3 -- per-DC artifact shape
================================================================================

QUESTION PUT TO THE OPERATOR: there is no `vr1-dc0-vips.yaml`; dc0's VIPs are inline in
`bundle.yaml` while dc1 has an overlay. Under ruling 1 both DCs need v6 legs, so the
asymmetry must break -- (i) symmetric (extract dc0 to its own overlay, base becomes
VIP-free, renderer has one output shape per DC) or (ii) asymmetric (dc0 v6 legs into
base, two renderer output modes forever)?

OPERATOR UTTERANCE (2026-07-25), verbatim:
  "Your question about 1 or 2, go with 1. Base bundle and everything else is applied
  via overlay."

EFFECT (option (i), symmetric):
- `bundle.yaml` becomes VIP-free and holds topology only.
- dc0's VIPs are extracted from base into `overlays/vr1-dc0-vips.yaml`, mirroring
  `overlays/vr1-dc1-vips.yaml`.
- Every per-DC value arrives via overlay, dc0 included. No DC is special.
- The renderer has ONE output shape per DC; Roosevelt's Nth DC matches its first.

IMPLEMENTATION NOTE for Code: this edits a render the operator has already validated
(`e898c3b`). Treat the extraction as a mechanical move -- the dc0 VIP values currently
in base (`keystone: 10.12.4.50 10.12.8.50 10.12.12.50`, and the peer applications on
the `.50`-`.60` band) move unchanged into the new overlay in the same commit that
removes them from base. Verify with `provider-bundle-check.py --overlay --dc vr1-dc0`
that the merged result is byte-equivalent to the pre-move merged result before the
dual-stack legs are added. Do the MOVE and the ADD as two commits, not one -- the move
is provably neutral, the add is not.
