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
| Mode | Pulls | Pushes | Schedules | Notes |
|---|---|---|---|---|
| mirror (default) | Yes | Yes | Yes | The normal active connection. |
| read_only | No (scheduled pulls paused) | No | Paused | The cooling-window state. Manual operator re-pulls still work. |
| off | No | No | Stopped | The 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_mirroredcompanies on the tenant.Zero
at_mirroredcontracts 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_onlygate 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_statusand 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_changesledger 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
AuditLogrow 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:
Every company has been cutover to
concorbit_native(see Cutover).Every revert window has expired (so no scope is mid-7-day-window).
Move to
read_only. The transition shows in the audit log; the AT credentials remain.Watch operations for the cooling window (default 30 days). The Coverage re-pull buttons still work if you want to spot-check.
With
BILLING_CUTOVER_NATIVE_GENERATION_ENABLED=truein place, run the wind-down tab's Final discovery + move to off. Tick the AT source frozen acknowledgement and confirm.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.