binding-plane-purpose-sweep-20260803.txt
========================================
Operator-requested (2026-08-03): "ovn-central should be in metal-internal. Complete a
bundle sweep for any other bindings that are bound to a plane that does not match the
planes intended purpose."

METHOD: extracted every binding of all 56 apps in bundle.yaml, classified each endpoint
against D-052's plane purposes (with Ceph/data-plane context rules), flagged deviations,
then VERIFIED each flag against the actual relation topology (a classifier flag is an
observation, not a conclusion).

D-052 PLANE PURPOSES (docs/design-decisions.md D-052):
  provider-public : public API endpoints + floating IPs
  metal-admin     : operator/MAAS/monitoring + admin API endpoint + "" default binding
  metal-internal  : ALL service-to-service control (internal API, shared-db, amqp,
                    certificates/secrets, cache, CLUSTER PEERS, ovsdb*, identity, inter-svc)
  data-tenant     : tenant geneve overlay (nova-compute:neutron-plugin, ovn-chassis:data,
                    ovn-chassis-octavia:data, octavia:ovsdb-cms)
  storage         : Ceph public (rbd client + mon + ceph control)
  replication     : Ceph OSD cluster replication

RAW FLAGS: 6. AFTER VERIFICATION: 1 real (ovn-central), 5 non-issues.

>>> CORRECTION 2026-08-03: my first pass called openstack-dashboard:cluster a 2nd real
>>> deviation. IT IS NOT -- it is D-072 / BUNDLEFIX-011, a RULED, as-executed fix documented
>>> in a comment RIGHT ABOVE the line in bundle.yaml (:667). I classified by binding VALUE and
>>> did not grep the governing D-NNN (CLAUDE.md requires that before touching a built surface).
>>> Reverting it would reintroduce the dashboard-VIP-HTTPS-dead bug D-072 repaired. NOT fixed.

--------------------------------------------------------------------------------------
REAL DEVIATIONS (2)
--------------------------------------------------------------------------------------
1. ovn-central (default)  metal-admin -> metal-internal   [RULED FIX]
   The "" default is what the charm's internal/admin/public cert resolution falls back to.
   On metal-admin (multi-space) it triggers LP #2044324 and ovn-central never gets a server
   cert -> OVN DB cluster never forms. Its certificates+ovsdb* endpoints already live on
   metal-internal; moving the default there makes ovn-central single-space for resolution.
   Operator ruling 2026-08-03: "ovn-central should be in metal-internal." (D-052 amendment
   for one app; isolation intact elsewhere.)

2. openstack-dashboard cluster  metal-admin   -- NOT A DEVIATION (CORRECTED). This is
   D-072 / BUNDLEFIX-011 (ADOPTED + as-executed 2026-07-05), documented in a comment directly
   above the binding (bundle.yaml:667): horizon renders haproxy's 443 backend on the CLUSTER
   binding address but only creates apache SSL vhosts for the default + public addresses, so
   cluster on metal-internal = TLS backend on a vhost-less address = dashboard VIP HTTPS DEAD
   (L4 check masks it). metal-admin matches the default binding so the backend lands on a served
   vhost. Reverting it reintroduces the exact bug D-072 fixed. DO NOT TOUCH. My sweep flagged it
   because it compared binding VALUES against generic D-052 purposes without grepping the
   governing D-NNN -- the lesson: a binding that deviates from the generic rule may be a RULED
   EXCEPTION, and CLAUDE.md requires grepping the D-NNN before calling a built value a defect.

--------------------------------------------------------------------------------------
VERIFIED NON-ISSUES (4) -- classifier false positives, confirmed against relations
--------------------------------------------------------------------------------------
3. octavia ovsdb-cms  data-tenant   -- NOT A FIX. The only ovsdb-cms relation is
   neutron-api-plugin-ovn:ovsdb-cms - ovn-central:ovsdb-cms; octavia:ovsdb-cms is in NO
   relation (octavia reaches OVN via the ovn-chassis-octavia subordinate). Dangling/inert,
   and D-052 explicitly lists octavia:ovsdb-cms under data-tenant anyway.
4. ceph-radosgw public  provider-public -- CORRECT. radosgw is a GATEWAY; `public` is its
   S3/Swift public API endpoint, not the Ceph public network.
5. ceph-radosgw object-store  metal-internal -- CORRECT. service-to-service API relation.
6. ceph-radosgw cluster  metal-internal -- CORRECT. radosgw peer HA, not Ceph OSD cluster.
   (ceph-radosgw:mon -> storage IS correct: it reaches ceph-mon on the storage plane.)

--------------------------------------------------------------------------------------
CONCLUSION: fix ONE binding -- ovn-central (default) -> metal-internal. Every other
binding either matches its plane's D-052 purpose or is a DOCUMENTED ruled exception
(openstack-dashboard:cluster = D-072). No other change.
