Status: DRAFT for the Code (jumphost) stream + operator ruling. Authored by the main-chat stream at repo HEAD 59a7c73 (2026-07-06). Read-only analysis; no live mutation and no committed-surface edit performed by main-chat.
Proposes: decision D-074 (PROPOSED; amends D-016). D-074 is next-free per bash scripts/ledger-scan.sh at this HEAD. NOTE: D-073 and DOCFIX up to 105 were consumed the same day by the jumphost stream -- Code must re-run the scan and re-confirm next-free before inserting the decision header. Do not hand-type it.
The stage-4 tenant CIDR guard in scripts/tenant-onboard.sh over-enforces relative to the onboarding contract it is supposed to implement, and separately has an overlap-detection hardening gap.
docs/tenant-onboarding-contract.md sec. 3, item 4): a tenant CIDR must be RFC1918 and non-colliding with (a) our allocations and (b) the client's own on-prem/VPN ranges they may later interconnect. The contract does not require non-collision with other tenants.tenant-onboard.sh stage 4 -- the grep -qw "$TENANT_CIDR" check run under admin_env against a cloud-wide openstack subnet list): it dies on any exact subnet-string match cloud-wide, which includes other tenants' subnets. So it forbids tenant-vs-tenant exact overlap that the contract never intended to forbid.grep -qw), so it MISSES partial/containing overlaps (e.g. a requested 10.20.20.128/25 against an existing 10.20.20.0/24). It is therefore simultaneously too strict on exact tenant matches and too loose on partial overlaps against ranges we must actually protect.Origin of the uniqueness behaviour (and a correction of the record): it is an IPAM artifact of D-016, which models a single 10.20.0.0/16 tenant pool and carves non-overlapping /24s from it. It is not a dataplane requirement. An earlier main-chat claim that the uniqueness rule was needed for "CAPI/Magnum reachability" was wrong and is retracted here: per D-035, capi-mgmt-v2 is single-homed on its own 10.20.0.0/24 and reaches workload clusters via their API-LB floating IPs and OpenStack via the API VIPs -- it never routes into other tenants' 10.20.x space, so overlapping tenant CIDRs cannot touch the management path.
Tenant private (overlay) CIDRs are tenant-chosen and MAY overlap across tenants. Non-collision is enforced only against a reserved-ranges registry (operator/infra allocations, section 3). NetBox (the IPAM apex) tracks the reserved/routed space; tenant overlay space leaves NetBox uniqueness tracking.
Rationale: this aligns the implementation with the onboarding contract's already-stated intent, and with the hard-isolation (SCS Domain Manager) persona. Overlap-allowed tenant CIDRs is the standard isolated-multi-tenant model -- it is why Neutron ships allow_overlapping_ips=true by default and why public-cloud VPCs let tenants pick arbitrary RFC1918. Globally-unique-per-tenant is the enterprise-private-cloud pattern (shared routed fabric, interoperating internal units), which is the opposite of what this cloud is.
Forward-only: existing tenants are not re-CIDR'd (northwind stays 10.20.20.0/24; design-decisions forbids transient-overlap re-CIDR).
PROPOSED means the operator has not ruled. Nothing in sections 3-4 is implemented until D-074 is ADOPTED.
Non-collision is enforced against these, using real subnet-overlap math (containment in either direction), not string equality:
| plane / allocation | CIDR (confirm live before wiring) |
|---|---|
provider-public (incl. API VIPs + provider-ext FIP pool) |
10.12.4.0/22 |
| metal-admin | 10.12.8.0/22 |
| metal-internal | 10.12.12.0/22 |
| data-tenant | 10.12.16.0/22 |
| storage | 10.12.32.0/22 |
| replication | 10.12.36.0/22 |
| capi-mgmt tenant network (D-035) | 10.20.0.0/24 -- OPERATOR DECISION: keep reserved? (recommend YES) |
| metadata service | 169.254.169.254/32 (link-local; not RFC1918; low concern) |
These values were read from docs/maas-as-built-reference.md by main-chat. Code MUST re-derive them from the authoritative live/modeled source (pre-flight PLANE_CIDRS / scripts/lib-net.sh / NetBox) before wiring the guard -- do not hardcode from this doc (hard rules 2 and 3: dynamic lookup, no inferred values). Centralize the list in lib-net.sh keyed by plane name, not as scattered literals.
allow_overlapping_ips. Read it live (juju config neutron-api ... or neutron.conf on a unit). If it is false, STOP -- flipping it is a wider blast radius that needs its own ruling; do not proceed on the assumption it is true.~/openstack-baseline/. (This foil doubles as the d011-05 P3 isolation foil.)tenant-onboard.sh)ipaddress) against the reserved-ranges registry only. Drop the tenant-vs-tenant check.tests/tenant-onboard/ with fixtures covering: exact tenant-vs-tenant overlap (now ALLOWED), partial overlap against a reserved range (REJECTED), exact match against a reserved range (REJECTED), and a disjoint range (ALLOWED). No script change ships without its harness.bash scripts/repo-lint.sh + the harness green before commit.tenant-onboarding-contract.md sec. 3.4: make explicit that tenant-vs-tenant overlap is permitted (the wording is already close; remove any implication of cloud-wide uniqueness).runbooks/tenant-onboarding-runbook.md: replace the "carve a non-colliding /24 from 10.20.0.0/16" guidance with "tenant CIDR is client-choice or the standard default; only reserved ranges are rejected."clientdocs/ intake field: reword "requested internal IP address" -> "requested internal network range (CIDR) -- optional; overlap-safe; default per policy" (also fixes the IP-vs-range wording mismatch).bash scripts/tenant-onboard.sh <devops-client> with TENANT_CIDR per the default policy ruled in section 6. Verify with scripts/tenant-assert.sh.Gain: implementation matches the contract and the hard-isolation persona; onboarding drops the "find a free /24" step; the intake field goes optional; clients can align to their own on-prem/VPN ranges; NetBox's uniqueness job shrinks to the routed space that genuinely must be unique (cleaner, and no global per-tenant IPAM registry to maintain across DCs for Roosevelt); the 256-/24 ceiling of one /16 stops being a scaling limit.
Lose / cost: debuggability -- an IP no longer uniquely identifies a tenant, so captures/triage need net+tenant context (mitigate with disciplined naming); no tenant-private-IP routing between tenants (an anti-pattern under hard isolation anyway); IPAM discipline narrows to reserved ranges rather than disappearing; the guard change touches a file Code is actively editing (coordination cost); D-016's /16 pool becomes vestigial (not reclaimed, just no longer enforced forward).
10.0.0.0/24) for all, or (b) client-choice with a fallback default. Recommend (b). This sets what the devops tenant receives.capi-mgmt 10.20.0.0/24 reserved? Recommend YES.allow_overlapping_ips confirmed true? (Phase 0.1 gates everything.)tenant-onboard.sh and the contract today (changelog addenda 21 / 23 / 26). The Phase-1 guard edit and all live steps are the jumphost stream's lane; main-chat authored this plan only. Code: pull and read this before resuming onboard-script work.59a7c73; re-confirm before inserting.