# Issue 979 Copy / Inherit-On-Create Authoring Guide

Status: design-authority guidance for pack authors and runtime reviewers
Scope: Flow-owned create-from-source actions, flat field mappings, dynamic
inherit, child fan-out, preview, transaction semantics, and compatibility
substrates.

## Purpose

Issue #979 makes create-from-source behavior a metadata-authored contract. A
pack author should be able to say "create this target graph from that source
graph" without asking generic L0 persistence, standard-action dispatch, or the
frontend to learn object-specific business rules.

This guide explains which metadata surface owns each part of the behavior.
It is intentionally object-neutral: examples use synthetic source/target names
so the same L0 contract can host a CRM pack, an ITSM pack, or any future app
pack without platform-code branches.

## Layering Contract

Generic platform code owns only the interpreter:

- standard-action dispatch and input validation;
- Flow execution, record lookup/create/update/delete primitives, and
  transaction boundaries;
- `_System_ObjectFieldMapping` loading and application;
- formula/reference evaluation;
- object, field, FLS, validation-rule, and persistence preparation;
- no-DML preview of supported Flow create graphs.

Application packs own product behavior:

- standard action rows;
- action schemas, defaults, guards, and internal access scopes;
- Flow definitions;
- field-mapping rows;
- formula fields/resources;
- layouts and create-screen metadata;
- child fan-out orchestration.

Tenant/org metadata may extend or override behavior through the same metadata
surfaces. Platform code must not hardcode source or target object names, field
names, record type developer names, picklist values, or workflow branches for a
specific create-from-source action.

## Authoring Shape

A create-from-source action should be modeled as:

1. `_System_StandardAction` binds the user-visible action to an orchestration
   Flow and declares permissions, action input schema, defaults, guards, and
   atomic intent.
2. The Flow receives the source record id and action inputs.
3. The Flow performs durable `recordLookup` steps for the source record and
   any required related records.
4. The Flow creates the target parent with:
   - `_System_ObjectFieldMapping` for flat snapshot copies, and
   - Flow input assignments / formulas for dynamic or literal values.
5. The Flow optionally looks up source child collections, loops over them, and
   creates target children with child field mappings plus a declarative parent
   lookup rewrite to the newly created target parent.
6. The same action can expose a no-DML preview image for human create screens.
7. Fault paths return structured action errors; required create-copy behavior
   must not leave a partial parent record committed.

## Snapshot Copy

Use `_System_ObjectFieldMapping` only for one-record, one-time field copies:

- source object to target object;
- action type / mapping group;
- source field to target field;
- optional source lookup context when the source record is reached through a
  relationship rather than passed directly.

Mappings are snapshots. They copy the source value into the target create image
at action execution time. They are not a formula language, traversal language,
loop construct, condition engine, child-clone engine, or standalone executor.

Input assignments in the same `recordCreate` may override mapped values when a
Flow author intentionally needs a literal or computed value to win for that
action.

## Dynamic Inherit

Dynamic inherit means the target value is derived from the source graph rather
than copied as a simple scalar.

Use formula-backed fields when the value must stay live after the target record
is created. The field remains calculated through metadata, so later source or
relationship changes are reflected by the formula read path.

Use Flow formula resources, relationship/reference traversal, durable
`recordLookup`, and explicit input assignments when the value should be
computed during create and stored as a snapshot. That keeps dynamic computation
in Flow/formula metadata without expanding `_System_ObjectFieldMapping` into a
second expression engine.

Pack docs should name which values are snapshots and which values remain live.
Do not rely on field names alone to imply this distinction.

## Child Fan-Out

Child fan-out is a Flow pattern:

1. Lookup the source child collection.
2. Loop over source children.
3. Create one target child per source child.
4. Apply child `_System_ObjectFieldMapping` rows for flat child fields.
5. Assign the new target parent lookup through Flow input assignments.
6. Put required child creation inside the same atomic action boundary as the
   parent create.

If the platform later adds a bulk optimization for this pattern, that
optimization must preserve the Flow authoring contract and Flow fault
semantics. It must not become a second product authoring surface.

Current preview support is conservative for same-run synthetic reads. A Flow
that needs to read a record created earlier in the same no-DML preview run must
wait for the #1044 synthetic read overlay contract before discovery should
advertise `previewEndpoint` for that shape.

## Preview Contract

Human create screens should call the standard-action preview endpoint rather
than reconstructing mappings in the browser. Preview is a no-DML projection of
the same action and Flow metadata used by Save:

- `_System_StandardAction` still owns action binding and permission checks;
- `_System_ActionSchema` still owns user-facing inputs;
- action defaults and guards still run;
- Flow `recordCreate` still applies field mappings, input assignments, formula
  values, and persistence preparation;
- response fields are projected through normal read-side object and field
  visibility.

Editable previewed fields may be sent back as user input only when object and
field metadata make them createable/editable for the user. Read-only, hidden, or
server-owned values may be displayed as summary data when useful, but final
execution must recompute them on the server.

Required preview failures should appear before Save. The UI may block Save for
supported preview failures, but Save remains authoritative and must rerun the
server action path.

## Transaction And Fault Semantics

Required copy, dynamic inherit, and child fan-out should run in the same action
transaction when partial creation would be invalid. Parent create, child
creates, and required copied/inherited values must commit or roll back together.

Record-triggered after-save flows are acceptable for optional enrichment, but
they are not the primary mechanism for required create-copy behavior because
they can expose a parent record before required copied data or children exist.

Fault paths should be metadata-authored and structured. A missing required
source value, failed child create, failed mapping lookup, or unsupported preview
shape should surface as an action/preview error instead of silently falling back
to partial data.

## Compatibility Substrates

`insertInheritFromLookup` and `_System_Object.ChildCloneRules` are retained only
as compatibility or low-level install/runtime substrates where already shipped.
They are not the preferred authoring model for new create-from-source behavior.

New behavior should prefer Flow-owned orchestration with:

- `_System_ObjectFieldMapping` for flat snapshot copies;
- Flow formulas and input assignments for dynamic create-time values;
- formula fields for live inherited values;
- Flow lookup/loop/create for child fan-out;
- standard-action preview for human create screens.

Any PR that expands `insertInheritFromLookup` or `ChildCloneRules` must state
why the change is compatibility/substrate work, why Flow-owned authoring cannot
cover that case yet, and what future extraction or migration path keeps #979 as
the design authority.

## Review Checklist

Use this checklist for PRs touching copy / inherit-on-create:

- No platform-code branches on concrete source or target object names.
- Flat copies go through `_System_ObjectFieldMapping`, not frontend mapping
  tables or persistence hooks.
- Dynamic values are formulas, Flow expressions, lookups, or input
  assignments, not overloaded field-mapping rows.
- Child fan-out is Flow lookup / loop / create with declarative parent lookup
  assignment.
- Required behavior runs inside an atomic action transaction.
- Preview and execution share the same metadata sources of truth.
- Preview hides unsupported shapes instead of publishing authoritative-looking
  partial projections.
- Tests use synthetic objects for generic substrate coverage.
- Any retained insert-inherit or child-clone behavior is documented as
  compatibility/substrate only.

References:

- Issue #979: https://github.com/pingcap-inc/NexusCRM/issues/979
- Synthetic read overlay follow-up: https://github.com/pingcap-inc/NexusCRM/issues/1044
- Standard-action preview contract: `docs/design/issue-979-flow-owned-create-preview.md`
- Preview synthetic-read split: `docs/design/issue-979-preview-synthetic-read-overlay-split.md`
