# Field History Eligibility

Status: all in-tree Update producers cut over; bounded legacy-data and
pre-cutover-binary compatibility remains.

## Authority

For a real field diff, Field History eligibility is the value of
`TrackHistory` in the exact schema admitted for the business mutation that
produced the diff. Runtime obtains that schema from its immutable request-bound
Mutation view. The legacy ServiceManager graph captures its MetadataService COW
schema once before entering the retry loop and reuses that same pointer for all
attempts. The request must not re-read `_System_Field`, consult another metadata
provider, reload the process cache during audit emission, or recompute the
decision after commit.

`recordAuditFieldChanges` is the single producer. Its caller passes the schema
already used by the mutation, and the traversal copies the decision into
nullable `FieldHistoryEligible`. Audit V2, its outbox worker, and the legacy
synchronous writer preserve a present value unchanged.
Generic Audit retains every diff regardless of this projection decision.
Create/Delete pseudo-history rows retain their explicit existing semantics.

The nullable states are:

- `TRUE`: the admitted Mutation view enabled history;
- `FALSE`: the admitted Mutation view disabled history;
- `NULL`: a pre-cutover producer or an unresolved field supplied no stable
  field provenance.

This makes retry, delayed outbox processing, worker restart, and duplicate
delivery deterministic. A request admitted against revision R keeps R's value;
publishing R+1 affects only later admissions.

## Cutover

The final read path is `FieldHistoryEligible = TRUE`. Until every producer and
worker is upgraded and old outbox work has drained, the compatibility reader is:

```sql
FieldHistoryEligible = TRUE
OR (
  FieldHistoryEligible IS NULL
  AND HistorySequence IS NOT NULL
  AND <the existing strict sequence/interval predicate>
)
```

A stamped `FALSE` must never fall back to an eligible legacy interval. A legacy
row without a sequence remains fail-closed. Timestamps are display/diagnostic
data and must not be used to invent serialization provenance.

The supported independently deployed L0 topology replaces Runtime API and its
workers from one frozen Core candidate through a stopped upgrade. It does not
run an ordinary old-worker/new-producer rolling pair. The release stages are:

1. Add the nullable storage/transport field and deploy the exact Runtime API
   and worker release that preserves it. This landed in #4654.
2. Request-bound Runtime producers always stamp the admitted decision. When
   every history-addressable diff (a diff with a stable FieldId) carries that
   decision, Records performs no sequence reservation. A generic-audit-only
   diff without a stable FieldId cannot enter either field-history read path
   and does not force authoritative siblings back onto the sequence path.
   The legacy ServiceManager Update path now also stamps from the schema it
   captured before its retry loop; audit emission no longer reloads its mutable
   process cache. Consequently every in-tree real-field Update producer emits
   boolean provenance and performs no sequence reservation. The reader retains
   the bounded fallback for rows from binaries predating this cutover and for
   historical rows. Drain pre-cutover outbox work and deterministically
   materialize legacy rows whose existing sequence/interval facts prove the
   result.
3. After every deployed producer binary is upgraded, all old outbox work is
   drained, and no eligible NULL rows remain, switch to boolean-only reads,
   stop metadata-transition sequence allocation, and delete the interval,
   prelock, retry/replay, and emergency-breaker machinery.

The NULL fallback is a temporary compatibility read, not a second long-term
authority.

`Flow.AtomicHistoryPrelocks` owns only first-attempt planning for legacy
`_System_FieldHistorySequence` rows; it is not a general mutation
serialization contract. `Flow.AtomicParentPrelocks` separately owns business-row
locking and remains active. Consequently an authoritative Runtime mutation does
not consume a declared history plan. If any stable field diff lacks eligibility
provenance, the mutation falls back to sequence reservation and consumes that
plan exactly as before. L1/L2 packs may remove redundant history declarations
independently; retaining one during this compatibility stage does not restore
an obsolete sequence lock to the Runtime hot path.

## Compatibility-only sequence contract

For binaries predating the producer cutover during stages 1 and 2,
`_System_FieldHistorySequence` and
`_System_FieldHistoryTrackingInterval` retain their existing strict predicate:
`StartedSequence < HistorySequence < EndedSequence`, with an open end treated
as unbounded. Their transaction-wide ordered locking, typed late-discovery
abort, root replay plan, rollback proof, and
`NEXUSCRM_FIELD_HISTORY_SEQUENCE_RESERVATION_ENABLED` circuit breaker remain
unchanged solely to support rolling compatibility and materialization. Current
Runtime and ServiceManager Update producers do not acquire or increment these
rows.

These mechanisms are not the new eligibility authority and must be removed at
stage 3. See [#4639](https://github.com/pingcap-inc/NexusCRM/issues/4639) for the
root-cause evidence and cutover acceptance criteria.

## Pack metadata writes

`EnsurePackOwnedField` remains a non-transactional, disabled-history admission
and physical-convergence surface. Pack history creation and convergence continue
through the active-transaction exact-owner
`BatchSaveFieldMetadataWithCustomizationPolicy` path during the compatibility
window. This migration does not move metadata authoring ownership into Audit or
Records.
