# Repeated reviewed customer corrections — v0.24

Current v0.25 adds [reviewed correction of an exact mistaken whole-customer merge](MERGE-CORRECTION.md). It reactivates the original record and optionally appends selected return moves without erasing this v0.24 history. This document retains the preceding selected-job checkpoint evidence.


This local stage supports selected exact jobs moving A → B → C, A → B → A, and longer reviewed sequences. Each move appends a numbered event with its prior event, original job version, new version, two exact customer IDs, owner, reason, preview and saved result. Returning a job creates a new correction; it never removes the earlier move.

## Owner walkthrough

1. Open Customer records, then Review record transfer. Choose Reassign selected jobs and two active exact customer records. Matching contact text is only a suggestion.
2. Select the exact jobs. Preview refreshes both saved customer versions and lists earlier moves, the next move, original documents, affected records and access changes.
3. Read the preview, enter a meaningful reason, then explicitly confirm. In-progress work, unfinished timers, unreviewed notes, active/paused repeat work, current/future bookings or inconsistent associations block the whole selected batch.
4. If validation or a stale preview is rejected, the reason and selected IDs stay in the form. Review a fresh preview and confirm again. Nothing is automatically resubmitted.
5. If the reply is lost or uncertain, keep the page open. The exact body and operation ID stay fixed; editing is disabled. Choose Check saved reassignment. A verified saved result is required before the form reports success. A new operation cannot replace an uncertain attempt silently.
6. Open the customer's history to read the numbered ownership sequence, first observed customer and current customer. Review another correction for this job starts a fresh selected-job review. Choose the desired active destination; the history never infers one from names or emails.

The form is memory-only; a closed tab or device loss can lose unfinished inputs. There is no durable offline correction queue, automatic reconnect send or phone guarantee. The server permanently retains the exact operation outcome alongside the transfer, so an explicit identical retry with its operation ID remains idempotent even after the general response cache is pruned. This stage does not claim browser reload recovery for unfinished transfer forms.

## What stays saved

Original enquiry text, requested dates and submitted-photo provenance remain original facts. Job IDs, document references and sealed snapshots, quote responses, amounts, payment and reversal history, time/material/source/field history, retired recurrence and calendar history remain linked to the same jobs. Current customer associations change; original document identity stays separate in screens, reports and recovery. First observed identity is labelled as observed, without inventing an earlier migration history.

A batch uses one business transaction after fresh owner/session/CSRF validation under the registry lock. Exact active customer IDs, versions, selected jobs, ownership chains, current associations and a conservative saved-state fingerprint are rechecked before any move. Changes to customer access, reset/setup token state or newly related saved records stale the preview. Competing requests either reuse one outcome or receive a conflict. A failure after any partial internal step rolls the entire batch back.

Both involved customer accounts are revoked on every correction. Existing portal sessions, setup/reset codes, legacy grants, customer photo sharing, feedback permissions and public publications do not return when a former customer becomes the current owner. Fresh invitations and individual permission reviews remain separate actions. Old follow-up reviews stay historical, even if follow-up exclusion is later cleared. A new next step requires a new source generation. Retired recurrence definitions included in any move stay retired after a return; a new definition must be separately created/reviewed. Device-note key/receipt scope includes the latest transfer identity, so returning to A never recreates the original A key or receipt access.

Previously transferred v0.23 device copies become inaccessible after upgrade because their ownership generation changes. Untransferred device-note scope is unchanged. No key recovery or remote ciphertext erasure is promised. Dataset/password/membership changes retain their existing access effects.

## Recovery and compatibility

Current backups are **format 13 / metadata 0.24.0**. Formats 1–12 keep their pinned schema contracts; the former customer validator is retained byte-for-byte as customer_recovery_v12.py. A real sanitized v0.23 format-12 fixture contains three singly moved jobs across two operations, sealed documents/payment, photos/field/source/feedback/gallery history, original intake/photo facts, retired recurrence and an empty second business. Its source commit, archive and fixture checksums are recorded in tests/fixtures/v0.23-customer-moves-format12.json.

Upgrade validates the exact old ledger and its full customer history, then atomically preserves its original six values and adds sequence 1 / no predecessor. Existing saved transfer plans/results remain byte-identical. New moves include the complete reviewed prior chain. Recovery checks each move against its preview, job/customer history, document event, associated-record event, sharing withdrawal and current binding. Missing, branched, reordered, mismatched and orphan ledgers fail before a restore destination is published. Chronological A → B → A is valid; merged-alias cycles are invalid.

Restores create a fresh folder and dataset identity, retain the ordered chain and evidence, revoke old credentials/sharing and verify a second backup. **v0.23 and older tools cannot restore format 13.** Retain the old snapshot and immutable older package for rollback; do not open a v0.24 data folder with an older release. Never migrate the protected v0.19 review or pending v0.23 owner demo in place.

## Scope and evidence

API, strict recovery, client and actual React component interaction tests use invented records. The React tests use jsdom and mocked HTTP outcomes; they are not signed-in Chrome, native focus/dialog or phone evidence. No v0.24 browser sign-in was requested or performed. The earlier v0.23 owner question remains separate and pending; its prepared tab/runtime and immutable release are preserved.

Selected-job repeated corrections are implemented. Whole-customer transitive merging, unmerge, generic customer import/backfill, destructive deletion, real identity verification, staff/customer browser breadth, mobile/offline queues, second-machine recovery and live deployment remain open. An active canonical customer with retired aliases can reassign selected jobs; aliases themselves cannot receive work or access. Further whole-customer merges of already moved work or alias-bearing sources remain blocked.

The local bounds are 25 selected jobs per correction (50 for the existing whole-customer merge), 5,000 transfer operations and 10,000 job moves. At the bound the whole operation is refused. This is a local prototype, not live SHS approval or full original-code parity. See customer-move-checks.json and customer-move-source-map.json.

## Final executed checks

774 full backend tests, 206 client tests, seven correction React interactions, 18 existing private-note React interactions, 90 structural renders and the production build pass. The initial full run had six failures; the follow-up return defect and test-fixture/version assumptions are recorded in customer-move-checks.json, with the initial and final logs retained. The existing bundle-size notice, TestClient deprecation and intentional oversized-pixel warning remain. Fresh extracted-package proof is delivered separately so it can name the immutable commit and ZIP checksum.
