---
id: SVC-PFM-MTD-layouts
title: Layouts Service Module
product_area: platform
module: metadata
repository: services-platform
source_module: modules/layouts
revision: 1
status: draft
design_intent: confirmed
origin: services-platform:docs/layouts.md (§2 the purpose is the authorization; §4a two console forms, Andrew 2026-10-11);
  R2-ARCH-001 v1.0 §3.3 (Andrew, 2026-10-19); custom objects architecture D-09 (approved 2026-10-18); R2-ARCH-002
  v2.0 (Andrew, 2026-10-22) for the publication column
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
owns:
- DOM-PFM-MTD-003
does_not_own:
- Purpose owners persist the assignment selections used by their records and settings.
- Each purpose owner publishes its administration keys.
- Console designers determine presentation document structure.
- Metadata owns registered categories and capability eligibility.
operations:
- operation_id: getLayoutsHealth
  intent: Return the Layouts build identity and health response.
  access: public
  permission: 'none: the shared health route (generated by the health-route factory as get<Module>Health)'
  realises: []
  published_to_submissions: 'not published: Operational health checks have no intake binding.'
- operation_id: createConsolePageLayout
  intent: Create a named console page layout under a purpose the caller administers.
  access: console
  permission: platform.layouts.create, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  - CAP-PFM-MTD-003
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: listConsolePageLayouts
  intent: Return paged console page layout definitions restricted to readable purposes.
  access: console
  permission: platform.layouts.read, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: getConsolePageLayout
  intent: Return the selected readable console page layout.
  access: console
  permission: platform.layouts.read, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: updateConsolePageLayout
  intent: Save a complete console page layout replacement at its version without changing purpose.
  access: console
  permission: platform.layouts.update, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: patchConsolePageLayout
  intent: Apply JSON Patch to the console page layout at its version while retaining purpose.
  access: console
  permission: platform.layouts.update, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: deleteConsolePageLayout
  intent: Remove the console page layout only after all assignments release it.
  access: console
  permission: platform.layouts.delete, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: createPortalPageLayout
  intent: Create a named portal page layout under a purpose the caller administers.
  access: console
  permission: platform.layouts.create, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  - CAP-PFM-MTD-003
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: listPortalPageLayouts
  intent: Return paged portal page layout definitions restricted to readable purposes.
  access: console
  permission: platform.layouts.read, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: getPortalPageLayout
  intent: Return the selected readable portal page layout.
  access: console
  permission: platform.layouts.read, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: updatePortalPageLayout
  intent: Save a complete portal page layout replacement at its version without changing purpose.
  access: console
  permission: platform.layouts.update, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: patchPortalPageLayout
  intent: Apply JSON Patch to the portal page layout at its version while retaining purpose.
  access: console
  permission: platform.layouts.update, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: deletePortalPageLayout
  intent: Remove the portal page layout only after all assignments release it.
  access: console
  permission: platform.layouts.delete, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: createConsoleForm
  intent: Create a named console form under a purpose the caller administers.
  access: console
  permission: platform.layouts.create, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  - CAP-PFM-MTD-003
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: listConsoleForms
  intent: Return paged console form definitions restricted to readable purposes.
  access: console
  permission: platform.layouts.read, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: getConsoleForm
  intent: Return the selected readable console form.
  access: console
  permission: platform.layouts.read, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: updateConsoleForm
  intent: Save a complete console form replacement at its version without changing purpose.
  access: console
  permission: platform.layouts.update, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: patchConsoleForm
  intent: Apply JSON Patch to the console form at its version while retaining purpose.
  access: console
  permission: platform.layouts.update, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: deleteConsoleForm
  intent: Remove the console form only after all assignments release it.
  access: console
  permission: platform.layouts.delete, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: createPortalForm
  intent: Create a named portal form under a purpose the caller administers.
  access: console
  permission: platform.layouts.create, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  - CAP-PFM-MTD-003
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: listPortalForms
  intent: Return paged portal form definitions restricted to readable purposes.
  access: console
  permission: platform.layouts.read, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: getPortalForm
  intent: Return the selected readable portal form.
  access: console
  permission: platform.layouts.read, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: updatePortalForm
  intent: Save a complete portal form replacement at its version without changing purpose.
  access: console
  permission: platform.layouts.update, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: patchPortalForm
  intent: Apply JSON Patch to the portal form at its version while retaining purpose.
  access: console
  permission: platform.layouts.update, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
- operation_id: deletePortalForm
  intent: Remove the portal form only after all assignments release it.
  access: console
  permission: platform.layouts.delete, with the purpose's own keys evaluated (the owner's administration keys, or
    for a read the record read key; platform.custom-objects.* and platform.custom-records.read for a custom object
    purpose)
  realises:
  - CAP-PFM-MTD-008
  published_to_submissions: 'not published: These configuration changes have no Submissions binding.'
events: []
jobs: []
integrations:
- system: Purpose owners (CRM today)
  direction: inbound
  contract: Record owners write assignments through the dedicated restricted database role; composite references
    protect resource kind, purpose and workspace agreement.
consistency:
- rule: A stored definition retains its original purpose and uninterpreted document content.
  kind: transactional
  compensation: Invalid changes are refused before commit.
- rule: Assignments retain matching workspace, kind and purpose references.
  kind: transactional
  compensation: Database refusal prevents incompatible assignment or deletion.
- rule: Replacements and patches require the loaded version and permitted lock state.
  kind: transactional
  compensation: Stale or locked changes leave the preceding definition.
- rule: Custom-object purpose access follows current local draft or active availability.
  kind: transactional
  compensation: Access is recomputed on read; archival needs no compensating definition rewrite.
evidence:
- 'services-platform at ad3f6a65: modules/layouts/aws/api/*.routes.ts, layout-access.ts, layout-operations.ts, purpose-permissions.ts,
  layouts.schemas.ts; purposes.ts; services/persistence/**; db/**; aws/platform.service.ts (LAYOUTS_PERMISSIONS);
  docs/layouts.md'
- '@rhythmsoftware/macroservice-http 0.19.0 dist/health-route.js (the generated health operation name)'
controls: [TC-AVL-001, TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-CRY-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---

# Layouts Service Module

## What This Service Is For

Layouts retains workspace forms and record-page definitions for console and portal use. A definition’s purpose identifies its category and supplies the purpose-specific access checks.

## Boundary

The service validates resource shape and size but leaves designer content to the console. Record owners choose compatible assignments in their own transactions; the registry supplies presentation eligibility.

## Operations in Words

Each resource supports create, list, read, replacement, patch and removal. Route permissions gate the surface, then purpose keys determine definition access. Reads hide unreachable definitions, changes require administration and removal reports assignments that still refer to the definition.

## Events and Jobs

The pinned Layouts module has no event or background job declaration.

## Consistency Guarantees

Versioned edits prevent stale replacement. Database composite references enforce assignment agreement and protect definitions during concurrent assignment and deletion.
