# Issue 1044 Preview Synthetic Read Overlay

Status: proposed implementation slice for issue #1044, stacked after the
lookup-before-create capability split in PR #1060.

## Problem

The no-DML standard-action preview path already captures `recordCreate`
intents and registers request-local synthetic IDs so later preview preparation
can validate lookup references without writing rows. The remaining unsafe
shape is a Flow that creates a row and then performs `recordLookup` against
that row, for example:

1. create parent A;
2. lookup A by a natural key;
3. create child B from the lookup output.

The previous overlay attempt appended raw preview-created rows after the
durable `QueryService` read had already applied object access, row access, and
field projection. That made the overlay look authoritative while letting raw
preview-only fields influence Flow filter matching or downstream field copies.

## Design

`QueryService` remains the read-projection owner. The Flow executor may keep
the request-local synthetic write set, but it must ask the query layer to
project synthetic rows before it treats them as lookup results.

The implementation adds a narrow optional interface on the query dependency:

```go
ProjectPreviewSyntheticRecords(ctx, objectName, rows, user) ([]SObject, error)
```

Only providers that can apply the same read contract as durable
`QueryWithFilter` should implement it. The production `QueryService`
implementation:

- checks object read access through the existing `checkObjectReadAccess` path;
- evaluates record access against each raw synthetic row unless the context has
  system or metadata-owned scoped read access;
- builds the same default field projection as `QueryWithFilter` with no select
  list;
- applies the same virtual/compound/system-permission projections used by the
  durable query path.

The Flow overlay then evaluates `recordLookup` filters only against the
projected rows. If a filter depends on a field that the query projection would
not expose, the synthetic row does not match. This prefers a false negative
over a preview that depends on data the live read path would not return.

## Capability Rule

Discovery may advertise preview for lookup-after-create graphs only when every
`recordLookup` in the reachable Flow graph is supported by the synthetic
overlay:

- the query provider implements the preview projection hook;
- lookup filter field names are syntactically valid;
- lookup operators and filter logic are supported by the in-memory matcher;
- direct synthetic ID propagation into later create/action inputs remains
  rejected unless the ID was first recovered through a projected lookup result.

Created-object before-create Flows with `recordLookup` remain fail-closed in
this slice. Those reads run inside persistence preparation rather than the
standard-action Flow's explicit lookup element, and need their own parity audit
before discovery can safely include them.

## Boundary Review

This remains L0 substrate only:

- no object names, field names, record types, profiles, or product workflow
  branches are introduced;
- pack-owned metadata decides whether a Flow does create/lookup/create;
- standard-action internal access stays metadata-scoped and is stripped from
  non-pack-owned child Flows by the existing child-context helper;
- preview IDs remain unguessable request-local provenance markers and never
  become durable record existence.

The old draft branch is intentionally not reused because it promoted raw
synthetic rows too early and carried broad unrelated frontend/API changes.
This slice keeps the write set local, moves projection authority to
`QueryService`, and limits discovery changes to the Flow capability gate.

## Verification

Focused tests should prove:

- `create -> lookup by natural key -> create` previews successfully when the
  synthetic row is projected by the query layer;
- fields stripped by the projection cannot satisfy lookup filters or flow into
  downstream creates;
- missing projection support keeps lookup-after-create discovery disabled;
- unsupported lookup filter logic keeps discovery disabled;
- durable lookup-before-create support from PR #1060 still passes.
