File builder layouts

Place module.files parts beneath one module.files workspace. All parts share the selected secured file, current permissions and metadata-save recovery state. Do not supply record identity to an action block.

The detail heading, actions, title, size, content type, description, tags, upload information, visibility scope, counts, version, status, preview state, timestamps and locks can be placed independently. See the Files row in modulePartCatalog.ts for exact names. Grouped detail/heading/actions/counts omit children explicitly placed elsewhere. Keep detail in the layout for its remaining editor, history and child panels.

Use core.container with disclosure-label and disclosure-state for expandable sections; the native controls remain mounted and use their existing action fences. Independently placed actions disable while metadata editing or recovery is active. Refresh after an uncertain save reads current state; it does not resend the write.

The metadata editor also exposes form-heading, form-scope, form-file-name, form-description, form-tags, form-save, form-cancel and form-current-metadata. These controls share one native HTML form owner even in different containers. Keep the form part to place its remaining fields, or rely on the fallback owner when only individual fields are placed. The recovery comparison can be positioned separately while the original draft/revision remains intact.

Upload controls are independently placeable as upload-heading, upload-file, upload-limit, upload-description, upload-tags, upload-record-query, upload-find-action, upload-record-choice, upload-scope, upload-personal-limit and upload-save. They share the native upload form through explicit form associations. The grouped upload/form/detail/list host retains unplaced fields; a fallback form keeps them available when none of those hosts is placed. Choosing a secured parent record removes top-level visibility choices because the child inherits its parent's scope. A standalone file still requires explicit visibility and location choices.

Give the comments part children to design its internal layout. Inside that comments block, place comments-heading, comments-notices, comments-list, comments-loading, comments-older, comment-form, comment-text, comment-limit and comment-save across your containers or disclosures. The comment form retains unplaced composer fields; notices and loading feedback remain visible unless explicitly placed elsewhere inside the block. A comments-list with children repeats comment-author, comment-created, comment-content and comment-remove for each secured comment. Each remove action uses the native comment identity and confirmation. Nested Files workspaces reset this context; orphan comment controls show a placement hint. A comments block without children retains its native grouped layout.

Give the versions part children to arrange versions-heading, versions-notices, versions-list, versions-loading, versions-older, version-form, version-file, version-help and version-save. A versions-list with children repeats version-number, version-current, version-name, version-size, version-type, version-uploaded, version-uploader and version-download for each secured version. The native panel owns reads, paging, upload feedback and the selected file identity. External upload controls share one form. Nested workspaces reset context; orphan controls show placement guidance. Read-only users retain permitted downloads. A versions block without children retains the native layout. File removal uses the existing native lifecycle and confirmation. No new routes, API permissions or SQL contracts are introduced by placement.

Source-only example guidance. Release and routed-tenant acceptance remain held.

Custom search and rows
The title, subtitle, upload action, query, type filter, Search and four pager controls can be placed independently. Search and query share one native form; changing pages uses the last submitted filters, not an unsubmitted query draft.

A list with children repeats its custom row layout for every secured FileSummary. Row parts expose title, description, size, type, version, preview availability, upload/update time, uploader, location, attachment count, favorite and Open. A list without children keeps the native directory. Actions always target their secured row, never a layout-supplied recordId. The current editor still replaces a custom list when that is the layout's only available form location.

placeable-files.json is a canonical Puck-compatible layout with custom rows and expandable editor/history containers. The existing secured typed clients back every action; no additional API routes are introduced.

Attachment controls and rows
Place attachments, attachment-heading, attachment-list, attachment-query, attachment-find, attachment-choice and attachment-save independently beneath the File workspace. Search and explicit record choice retain the native secured API; the submit button and required choice share one form even across containers. An attachment-list with children repeats attachment-row-title, attachment-row-module, attachment-row-created and attachment-row-remove for each secured attachment. Without children it retains the native list. Nested workspaces reset row context. Detach confirms the exact record link and retains the file and linked record. Controls lock while confirming or writing; an uncertain result requires a read refresh and never automatically repeats the write.
