Contact controls in a custom layout

Use one module.contacts workspace and place module.contacts children beneath it with props.part. Layout containers, expandable core.container sections (props disclosure-label plus disclosure-state open/closed), and other feature workspaces can sit between the Contact workspace and its parts. The nearest matching Contact workspace supplies the state and actions. Do not place the same part twice.

Detail parts
heading, actions, record-title, record-type, record-location, favorite-action, edit-action, remove-action, scope, channels, email, phone, mobile, relations-count, activity-count, address, notes, secure-fields, related.
The existing detail panel supplies unplaced groups; each group omits its separately placed children. Existing activity, dates, custom-fields, export and duplicate-warning parts remain available.

Create/edit parts
form-heading, form-scope, form-type, form-first-name, form-last-name, form-company, form-email, form-phone, form-mobile, form-address, form-address-line-2, form-city, form-state, form-postal-code, form-country, form-notes, form-custom-fields, save-action, cancel-action, form-errors.
These parts appear only while the workspace is creating or editing. Each control belongs to the same HTML form, even outside its DOM subtree. Keep the native form part (or detail/list fallback) to expose unplaced controls. If a layout has neither form, detail nor list, the workspace renders the remaining form before its custom children. Partial placement must not hide required inputs.

Example layout recipe
- Directory column: header, filters, list, pager.
- Profile column: record-title, record-type, actions, email, phone, notes, scope.
- Editor panel: form-heading, form-first-name, form-notes, form-scope, form-custom-fields, save-action, cancel-action, form-errors.
- Remaining controls: form (or detail).
Use your own container styling and responsive layout. Each child uses a unique block _id, _type module.contacts, props {part: "form-notes"}, and children []. The surrounding Contact workspace uses props {part: "workspace"}. This is the canonical native block contract, not a new REST endpoint or permission grant.

Behavior
The existing typed Contact client and secured routes remain authoritative. Visibility is explicitly selected for every create; moving the scope selector does not infer Personal, a role, or All locations. Mutations share the workspace lock. Draft edits trigger the existing discard confirmation. Closing and reopening starts a fresh draft. Metadata decides which fields are writable. Errors remain visible through form-errors or the workspace fallback.

Cross-feature work
Use the workspace contextKey and another feature's recordFrom to share the selected record. See related-calendar-builder.txt for the separate, explicit Calendar creation and link workflow. A page layout never grants record or action authority.

Current limits
See placeable-contacts.json for a canonical page containing a custom repeated row layout and an expandable writer. Header/search/pager parts: eyebrow, title, subtitle, customize-action, new-action, query, type-filter, sort-filter, search-action, page-size, previous-action, page-status, next-action. A list part with children repeats those children for every secured row. Its row parts are row-open, row-title, row-first-name, row-last-name, row-company, row-email, row-phone, row-mobile, row-type, row-location, row-updated and row-favorite. Row actions ignore any block-supplied recordId. Lists without children retain the native directory/portfolio layout.

Secure-field and related-item internals, export/preferences/duplicate panels, and portfolio summary figures remain grouped. The shared renderless custom-field control API supports individual dynamic fields; the native form-custom-fields part remains a group. TD-55 is still open. This source has local fixture/browser verification; runtime and published Developer Kit activation remain held.
