# Writing the change list

The audit never edits the CRM. Fixes leave as a written change list that an admin applies after approval. Template: [../assets/change-list-template.md](../assets/change-list-template.md).

## Rules for the list

- One change request per hypothesis. "Owners flip between rotation and enrichment" is one request; archiving unused fields is another. Mixing them makes the main fix impossible to verify.
- A test depends only on its own request. If it also needs another fix, make that fix its own request and reference it.
- Order: stop harm first (consent writers, exposure, destructive automation, privileged access), then stop conflicting writers and duplicate creation, then restore reporting correctness, then structural redesign, then hygiene.
- Every item names the baseline: CRM, instance label, environment, read time.
- Every item names entities by internal name and ID and quotes the current setting. "Fix the owner workflow" is not actionable.
- Every item states what could break, the test with its approvals and test data, the rollback with its window, what rollback does not undo, the owner, the verifier and, for irreversible items, the approver.
- Merges, deletes, consent or marketing status changes and permission removals need a named approver.
- When a fix will move a reported number (opted-in counts fall, pipeline value drops to the record-list value), say so and tell the reporting owner before release, so a correction is not read as a performance drop.
- When a WARN gate gets an owner and a date here, copy them into the inventory's `gate_owners` so the verdict can reach ready.

## Rollback windows (verify at run time)

- HubSpot: archived properties restore for 90 days, then are deleted. Deleted workflows restore for 90 days, as new inactive workflows without their history. Restore CRM changes rolls back a named import, integration or workflow for 14 days and needs a Super Admin. Merges cannot be undone.
- Salesforce: the Recycle Bin keeps deleted records for 15 days, then schedules them for permanent deletion with no guaranteed exact time. A deleted custom field and its data restore for 15 days, or until the org permanently deletes them. Merged records are deleted, and the survivor keeps its ID.
- Attio: a merge creates a new record ID and the originals can no longer be read or written. Undoing an import removes the imported records but not lists or attributes created with it.
- Permission changes are not versioned anywhere. Record the before state in the change list.

## What rollback never undoes

- Messages already sent, and owner or task notifications already delivered.
- Values already synced to other systems (billing, warehouse, ad platforms, the other CRM).
- Enrolments and their history, sequence steps already run.
- Reports and exports already shared.

## Example entries (Acme Cloud, portal 1234567, read 2026-11-01)

```markdown
### CR-1 Stop WebinarCo writing newsletter_opt_in (FLD-03 FAIL, gate)
- Entity: integration WebinarCo (marketplace app), field mapping attendee consent -> contacts.newsletter_opt_in.
- Current setting: mapping on; writes newsletter_opt_in = true for every attendee. 37 opted-out contacts
  were flipped back to opted in within the window (property history, EV-02).
- Change: remove the mapping. Keep webinar_attended. Record any webinar consent in its own field
  owned by the privacy owner, if the privacy owner wants one.
- Why: consent has one permitted writer (the preference centre, plus the unsubscribe link and documented manual
  edits); an event app is not one of them.
- Could break: any segment that relied on webinar attendees being opted in. That reliance was the defect.
- Test (approved by the marketing ops manager): register one flagged test contact (test_record = true,
  jane@example.com) for a test webinar, mark it attended, and confirm newsletter_opt_in is unchanged
  in property history.
- Restore: for the 37 contacts, set newsletter_opt_in back to the value before the WebinarCo write, from
  property history. Within 14 days of a change, a Super Admin can filter Restore CRM changes to the
  WebinarCo integration instead.
- Rollback: re-enable the mapping (not recommended). Does not undo: newsletters already sent to the 37 contacts.
- Numbers that move: opted-in count falls by at least 37. Privacy owner and marketing ops told before release.
- Owner: marketing ops manager. Verifier: privacy owner. Approver: privacy owner.

### CR-4 One owner writer for contacts.hubspot_owner_id (FLD-02 FAIL, INT-06 FAIL, AUTO-09 FAIL)
- Entities: workflow "Inbound rotation" [1003] (Rotate record to owner, overwrite on); EnrichCo field rule
  writing hubspot_owner_id on update.
- Current setting: both write owners on the same contacts with no precedence rule; writer_history.py shows
  flip-flops on 4 of 12 records changed in 30 days: 3 between rotation and EnrichCo, and 1 where EnrichCo
  reversed a rep's correction (samples 1001, 1002, 1003, 1004; evidence EV-01).
- Change: turn off EnrichCo owner sync on update. In "Inbound rotation", turn overwrite off for contacts
  with lifecycle stage Customer or an open deal. Write the precedence rule in decisions.md:
  rotation owns first assignment; humans own changes after that; no integration writes owner.
- Could break: territories EnrichCo assigned by country. Confirm with the sales lead that rotation covers them.
- Test (approved by the RevOps lead): three flagged test contacts (new lead, existing customer, contact with
  an open deal) through the workflow, then one EnrichCo run. Expected: only the new lead gets an owner from
  rotation, and no owner changes after the EnrichCo run.
- Restore: owners for the flip-flop records from property history, last value set by rotation or a human.
- Rollback: re-enable the EnrichCo rule and overwrite. Does not undo: owner notifications and tasks already sent.
- Numbers that move: pipeline by owner shifts for the restored records. Sales lead told.
- Owner: RevOps lead. Verifier: sales ops. Approver: sales lead.
```

## Release evidence to ask for

The admin closes each item with three answers:

- Did the configuration change as written? (settings capture or definition export after the change)
- Did behaviour match on test records? (the test cases and their observed results)
- Does the destination record or report show the expected result? (record history, reconciliation)

A yes to the first question does not stand in for the other two.

## Applying approved changes with agent tooling

If the team wants an agent to apply approved items, use the vendor's own tools with dry runs first: for HubSpot, the Agent CLI and its agent-cli-skills with `--dry-run` and a small batch; for Salesforce, a deployment reviewed in a sandbox. Check the agent's write permissions with the agent-write-safety skill if installed. This skill does not write.
