Newer
Older
openstack-caracal-dc-dc / docs / audit / operating-model-plan-20260725.md

Operating-model plan: NetBox -> deploy (planning session input)

Date: 2026-07-25. Branch: dc-dc-stage4-phase3-maas-deploy. Status: ADVISORY / planning input. Adopts nothing. docs/CURRENT-STATE.md remains the sole status authority (GA-R1). Authored in the Chat design seat; PINNED for a dedicated operator planning session. Companion to: docs/audit/decision-recon-20260725.md, docs/audit/committee-20260724-track2-bundle-render.md, and the PROPOSED NetBox-coupling decision in docs/design-decisions.md.

A PLAN, not a decision. Deliberately NOT a D-NNN entry: the operator asked for a recommendation plus a dedicated planning session, so the target operating model is not ripe for ratification. Implement NOTHING from this file.

Authored against repo HEAD bc9a2df.

================================================================================

1. The model as the operator described it (2026-07-25)

================================================================================

Draft changes in NetBox -> a tool or queued item reads the changes; operator approves before anything begins -> OpenTofu / MAAS / Juju (whichever the change requires) processes the deployment, assignment or change -> the process is as automated and self-healing as possible without operator interaction -> operator is notified on completion, with logs entered and artifacts created -> operator is given next-step instructions derived from the process

This is the standard source-of-truth-driven infrastructure automation shape. The three recommendations below are refinements to it, not a different mechanism.

================================================================================

2. Recommendation A -- the approval gate belongs on the RENDERED DIFF

================================================================================

Approving "someone changed a prefix in NetBox" does not tell the operator what will happen to the cloud. Approving "here is the resulting overlay diff, the tofu plan, and the validator report" does.

NetBox draft -> renderer emits artifacts onto a git branch -> THE BRANCH DIFF IS THE CHANGE REQUEST -> operator approves the diff -> apply (tofu -> MAAS -> Juju, each gated as today)

  • Costs nothing extra: the artifacts are generated either way; the diff is free.
  • Rollback for free (git revert); audit for free (the diff IS the record, with reviewer and timestamp attached).
  • Matches existing discipline exactly: verify-before-mutate wants a verification artifact, and the diff plus validator report IS that artifact.
  • Keeps intent store and executable artifact reconciled by construction, not by trust.

================================================================================

3. Recommendation B -- split "self-healing" in two

================================================================================

SAFE, unattended -- CONVERGENT RE-ASSERT of declarative state:

  • re-run the renderer; diff generated output against committed output
  • re-apply idempotent configuration
  • re-run validators and behavioural assertions (provider-bundle-check.py, cloud-assert.sh) These read, compare and report. Run them on a timer.

NOT SAFE unattended -- AUTONOMOUS REMEDIATION of observed drift:

  • On a live multi-tenant cloud the remediation can BE the outage, and the blast radius crosses tenant boundaries. An automated actor that "repairs" a VIP or reassigns a prefix while tenants are running can take down a plane.
  • It contradicts the standing rules directly: destructive steps gated individually and never batched; no live re-architecture inside a step.

RECOMMENDATION: self-healing is READ / VERIFY / REPORT plus idempotent re-assert. Drift detection emits an alert AND a proposed remediation diff; the mutation stays gated. The automation's job is to make the operator's decision instant and well-evidenced, not to make it unnecessary.

================================================================================

4. Recommendation C -- the draft primitive already exists

================================================================================

No NetBox branching plugin is required. Code built the source separation in bc9a2df:

netbox/prod-draft-dump.py -> netbox.baldurkeep.com, FROZEN v1 reference (4.5.8), read-only for the duration of VR1 netbox/office1-record-dump.py -> office1-netbox 10.10.1.10:8000, the VR1 WORKING APEX / "the RECORD" (4.6.4). Read-only, token from environment, never embedded or printed, one script per SOURCE so the source can never be confused netbox/draft/vr1-draft.json (draft) vs netbox/draft/vr1-office1-current-20260725.json (record snapshot)

So: DIFF DRAFT AGAINST RECORD, and that diff is the intent change feeding the same approval gate in section 2. Low-tech, already committed, keeps write-back deferred per DOCFIX-195, and adds no new dependency to the airgap mirror (D-107).

================================================================================

5. Known gap to close in the session

================================================================================

GitBucket has no Actions-style CI runner, so "the renderer runs automatically" needs a host: a jumphost systemd timer, or a NetBox webhook plus a worker. Either way an automated push needs a GitBucket credential over HTTPS basic auth, because SSH access is v2-deferred. That is a security-ledger row (credential scope, storage, rotation), NOT a design decision, and it should be opened before any automated push exists.

SEQUENCING NOTE: the operator intends to migrate from GitBucket to an in-house product, SpryGit. The runner and API surface this operating model needs are therefore REQUIREMENTS INPUT for SpryGit -- captured in docs/audit/sprygit-requirements-inputs-20260725.md. Do not design around GitBucket's current limits as if they were permanent.

================================================================================

6. Agenda for the planning session

================================================================================

  1. Ratify or amend the approval-gate placement (section 2).
  2. Ratify the self-healing split; enumerate exactly which checks run unattended (3).
  3. Decide intent-store mechanics: NetBox draft objects, draft-vs-record JSON diff, or both at different tiers (4).
  4. Decide the runner and its credential posture; open the security-ledger row (5).
  5. Decide whether generated artifacts are committed (recommended) or produced at deploy time.
  6. Decide the notification and next-step surface: what the operator receives on completion, and how "next steps" derive from which gates passed.
  7. Decide what this becomes: one process D-NNN (GA-R3: it needs architectural consequence and a Roosevelt-delta to qualify), or a process runbook governed by an existing decision. Doubt resolves DOWN to OPS.

================================================================================

7. Research scope requested by the operator -- NOT YET PERFORMED

================================================================================

The operator asked for best-practice workflow options grounded in real-world documentation and processes used by datacenters running this stack. That research has NOT been done; nothing in this file is its result. Candidate sources:

  • Canonical Charmed OpenStack reference architectures and operations guidance; terraform-provider-juju; Juju bundle/overlay lifecycle practice.
  • Sovereign Cloud Stack (SCS) operational documentation -- directly relevant, since this deployment implements the scs-0302 Domain Manager persona (D-051, D-064).
  • NetBox and Nautobot source-of-truth-driven automation, golden configuration, and intended-vs-actual reconciliation models.
  • GitOps control-loop practice for infrastructure, specifically where the approval gate sits relative to render and apply.
  • MAAS plus OpenTofu substrate lifecycle patterns for multi-site deployments.
  • OpenStack Operations Guide material on change management and drift.

For each: what the pattern is, who runs it at datacenter scale on this stack, where the approval gate sits, what it automates unattended, and what it deliberately refuses to automate. Deliverable: options with trade-offs plus a recommendation measured against the Roosevelt-delta fitness function.