# 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.
