Concorbit HelpAll guides →

Wind Down

Wind-down

Wind-down is the operational quieting of the Autotask connection after every company has been cutover to concorbit_native. It is the connection-level counterpart to per-company Cutover. The lifecycle has three states: mirror, read_only, and off. Wind-down moves through them in order, with hard gates at each step that exist to make double-billing impossible.

The tab lives on Settings, Autotask, Wind-down.

The three modes

ModePullsPushesSchedulesNotes
mirror (default)YesYesYesThe normal active connection.
read_onlyNo (scheduled pulls paused)NoPausedThe cooling-window state. Manual operator re-pulls still work.
offNoNoStoppedThe terminal state. is_active stays true so the connection can be reactivated; the credentials stay encrypted on file.

is_active and mode are distinct. is_active=false is a hard disconnect and wins over mode. Mode is only meaningful while is_active=true. A disconnect resets the mode to mirror, so a future reconnect starts cleanly.

The mirror, read_only, off gate matrix

AutotaskConnectionModeService::gateStatus is the read-only preview the UI renders, computed against the same evidence the actual transitions use.

To enter read_only from mirror:

  • Zero at_mirrored companies on the tenant.

  • Zero at_mirrored contracts on the tenant.

  • Zero open revert windows (no company is still inside its 7-day post-cutover window).

  • No in-flight initial sync.

This is a hard gate. read_only pauses the AT invoice pull that billing parity's on-demand compute reads from. Going read_only while any scope is still at_mirrored would starve the parity evidence of fresh AT invoices right when it matters most. The zero-open-windows clause also stops a 7-day revert window from expiring while pulls are paused.

To enter off from read_only:

  • Every read_only gate above, plus:

  • BILLING_CUTOVER_NATIVE_GENERATION_ENABLED=true (the cutover master switch must be on, otherwise concorbit is not generating native invoices).

  • The cooling window has elapsed (default 30 days in read_only, configurable per tenant).

  • An explicit AT source frozen acknowledgement from the operator.

  • A FRESH final company and contract discovery has just been run, so a scope created while pulls were paused is visible to the gate.

The off transition runs the final discovery inside the locked transition, with the authoritative zero-count read inside the row lock. A scope imported by the discovery is counted by the gate that decides the same flip.

To reactivate from off back to mirror:

  • Resets initial_sync_status and clears per-entity cursors.

  • Queues a full re-sync via AutotaskInitialSyncOrchestrator::start.

  • Holds the connection in a non-mirror state until the orchestrator has queued; only then flips to mirror.

This sequence is wrapped in a per-connection Cache::lock so the whole reactivation is serialised. The initial-sync guard covers the window between cursor reset and the first chunk.

What pauses in read_only

Every scheduled AT interaction is gated on canPull() and canPush(), which both return true only in mirror. In read_only these pause:

  • The four scheduled reads: reconcile-charge-billing, reconcile-tickets, parity-check, extend-blocks.

  • The seven push services (tickets, replies, time entries, attachments, quotes, quote decisions, contract adjustments).

  • The four on-save push observers.

  • Auto-dispatched RetryBlockedTicketsJob.

Operator escape hatches keep working: autotask:sync and parity-check accept --allow-wound-down and the Coverage tab's re-pull, re-parity, and reconcile-all buttons pass that flag automatically. These are deliberate spot-checks, not policy violations.

The final reconciliation period

Before flipping to off, the wind-down tab runs a final company and contract discovery as part of the locked transition. This re-pulls company and contract lists from AT one more time, so a scope created during read_only (while pulls were paused) is visible to the off-gate. The gate is then re-evaluated inside the lock against the freshest counts.

This is the safety belt against the trap "a customer signed up in AT after we wound down to read_only, but concorbit never saw it".

The AT source frozen acknowledgement

Going off requires an explicit operator checkbox: AT is the source of record no longer. The acknowledgement is captured on the mode-change ledger row alongside the user, the reason text, and the gate snapshot. It is not a precomputed gate, it is an attestation, so the audit row carries the operator's confirmation explicitly.

Audit trail

Every mode change writes two artefacts:

  • An autotask_connection_mode_changes ledger row, one per transition, carrying from-mode, to-mode, user, reason, AT-source-frozen ack, gate evidence snapshot, and any blocking reasons (for refused transitions).

  • An AuditLog row on the connection itself.

The mode-change history is rendered on the Wind-down tab, oldest first, with the gate evidence preserved.

Rolling back after wind-down

Once a connection is off, the per-company BillingCutoverService::revert() refuses (the connection is wound down). Rollback after wind-down is a manual re-slave runbook: reactivate the connection (off, mirror), let the full re-sync complete, then re-stamp scopes as needed. There is no one-click reverse from off to at_mirrored. That is by design, the off-gate makes sure rollback is never needed in normal operation.

When to wind down

The recommended order:

  1. Every company has been cutover to concorbit_native (see Cutover).

  2. Every revert window has expired (so no scope is mid-7-day-window).

  3. Move to read_only. The transition shows in the audit log; the AT credentials remain.

  4. Watch operations for the cooling window (default 30 days). The Coverage re-pull buttons still work if you want to spot-check.

  5. With BILLING_CUTOVER_NATIVE_GENERATION_ENABLED=true in place, run the wind-down tab's Final discovery + move to off. Tick the AT source frozen acknowledgement and confirm.

  6. The connection is now in off. The credentials stay; the calls stop.

To retire entirely, Disconnect the connection after off. This is the only reset that takes mode back to mirror, but it also wipes the credentials.