# Current-State Reader

Status: Frozen architecture note
Owner: Search Platform Architecture

## 1. Scope

This document defines the internal execution design of `Current-State Reader`, the write-authoritative point-read/OCC helper used by Flow-B read-modify-write routes before canonical mutation emission.

This document is subordinate to the canonical owner stack:
- machine-readable contract: `api/proto/searchfabric/v1/search_fabric.proto`
- internal owner file for this boundary: `api/proto/searchfabric/v1/current_state_reader.proto`
- public ingest/query/control semantics: `docs/specs/core/search-fabric-api.md`
- canonical error registry: `docs/specs/core/error-codes.md`
- system topology and state ownership: `docs/specs/core/search-fabric-architecture.md`

It must not redefine:
- public query RPCs or query-plane snapshot semantics,
- public `MutationBatch`, `MutationAck`, or `RowMutation.expected_commit_ts` semantics,
- committed-manifest visibility ownership,
- source-facing Elasticsearch/Turbopuffer/TiDB wire behavior already owned elsewhere.

## 2. Canonical Position in the System

`Current-State Reader` sits only on the Flow-B prewrite path:

```text
External/Trusted Flow-B caller
  -> Unified Edge/Auth Ingress or trusted service identity
  -> Ingest Gateway
  -> Current-State Reader
  -> Ingest Gateway deterministic point-read/evaluate/canonicalize
  -> Ingest Broker
  -> Write Planner
```

The checked-out core architecture constrains that placement:
- it is a private Flow-B point-read/OCC helper, not a query-plane surface,
- it is not on the Flow-A `TiCDC -> CDC Adapter` path,
- selector/by-query materialization remains a `Query Broker` responsibility under admitted snapshot semantics.

`Current-State Reader` therefore exists to answer one question that the stale-tolerant query plane cannot answer truthfully enough for write admission:

```text
What is the latest write-authoritative state of doc_id X on collection Y right now?
```

## 3. Responsibilities and Non-Responsibilities

### 3.1 Responsibilities

`Current-State Reader` is responsible for:

1. Serving single-document current-state lookups keyed by authoritative `CollectionRef` plus canonical `doc_id`.
2. Returning the latest current-version marker needed to derive deterministic `RowMutation.expected_commit_ts`.
3. Returning the current row payload, or a route-scoped canonical projection of it, when Flow-B deterministic point-read/evaluate/canonicalize requires merge/noop evaluation.
4. Preserving write-authoritative semantics for Flow-B point-read/OCC routes instead of inheriting query-plane stale-snapshot rules.
5. Failing closed when authoritative current-state truth cannot be established under the active schema-generation fence.

### 3.2 Non-Responsibilities

`Current-State Reader` is not responsible for:

- public `ExecuteQuery`, `StreamQuery`, `GetReadiness`, or `GetCollectionStatistics`,
- by-query selector materialization or global row-set discovery,
- source response classification such as `created` / `updated` / `deleted` / `not_found` on final success,
- `commit_ts` assignment,
- manifest publication,
- background compaction/GC,
- lifecycle scheduling,
- durable truth ownership separate from the write/query architecture.

Authoritative source response classification still comes from post-apply `MutationAck.success.item_outcomes[]`, not from prewrite guesses.

## 4. Authoritative Read Model

### 4.1 What “Write-Authoritative” Means

For this component, “write-authoritative” means the returned state must be suitable for:
- compare-and-set lowering into `RowMutation.expected_commit_ts`,
- deterministic merge evaluation for admitted update-style routes,
- gateway-local noop detection where the canonical API allows it.

That requirement is stricter than ordinary query serving:
- query serving is bounded by admitted `effective_read_ts` and committed-manifest visibility,
- current-state reading must answer against the latest write-authoritative row version accepted by the write path for the target row.

### 4.2 Allowed Authority Set

`Current-State Reader` may be realized using any internal composition that truthfully reconstructs the latest row version for one document, but the authority set must remain subordinate to the checked-out write/query design:
- committed manifests remain the durable immutable base,
- retained write-path delta / anchor state may contribute newer row versions ahead of the last query-serving committed frontier,
- winner order for competing versions remains the canonical tuple:
  - `commit_ts`
  - `source_partition`
  - `source_epoch`
  - `source_seq`

The component may share physical code or storage primitives with readers/writers, but it must not inherit:
- query-plane `effective_read_ts` waiting,
- query-plane continuation or token semantics,
- a second independent durability or visibility truth store.

### 4.3 Route-Scoped Output Shape

The minimal truthful output for one lookup is:
- row presence (`exists` vs absent),
- `latest_commit_ts` with canonical absent-doc value `0`,
- optional current canonical row payload or route-scoped projection when merge/noop evaluation needs it.

The component must not invent a public protobuf shape for this result.
Its request/response carrier is now pinned by `api/proto/searchfabric/v1/current_state_reader.proto` as the internal boundary between `Ingest Gateway` and the current-state helper.

## 5. Read Rules

### 5.1 Single-Document OCC

For pure OCC/version checks, the reader may use the minimal version-only path:
- resolve `(CollectionRef, doc_id)`,
- fetch the latest write-authoritative version marker,
- return `latest_commit_ts` (`0` when absent).

This is sufficient for:
- create-only lowering (`expected_commit_ts=0`),
- explicit `if_seq_no` validation,
- delete/update routes that already know the target row identity and only need OCC.

### 5.2 Deterministic Merge / Noop Evaluation

For admitted read-modify-write routes such as the Elasticsearch `_update` subset, the reader must be able to return enough current-state payload for gateway-local deterministic evaluation:
- current canonical row when the document exists,
- absent-doc state when it does not,
- schema-fenced field interpretation under the active generation.

The gateway may then:
- compute merged patch semantics,
- detect canonical noop when allowed,
- lower the resulting write plan back into canonical `RowMutation` form.

The gateway must not backfill lifecycle carry fields from this read path when the canonical contract requires explicit payload carry.

## 6. Failure Handling and Recovery

Failure rules:
- unresolved collection scope, stale schema fence, or missing authoritative current-state truth must fail closed before mutation emission,
- the component must not silently fall back to stale query-plane snapshots,
- transport/dependency failure remains an internal availability error, not a synthetic successful read.

Recovery rules:
- `Current-State Reader` owns no second durable truth source,
- restart recovery must be reconstructable from the same committed manifests and retained write-authoritative delta/anchor inputs already owned by the checked-out architecture,
- unpublished local caches or ephemeral indices are disposable accelerators only.

## 7. Deployment Guidance

The core architecture allows this component to be:
- a private stateless service, or
- a tightly coupled internal module packaged with the ingest bundle.

Either form must preserve the same invariants:
- no public surface,
- no CDC-path ownership,
- no query-plane stale-snapshot semantics,
- no second visibility/durability authority.
