---
id: CAP-PFM-MTD-011
title: Control Custom Record Audiences
feature: FEAT-PFM-MTD-04
product_area: platform
module: metadata
revision: 1
status: draft
product_intent: confirmed
implementation_evidence: partially-observed
supersedes:
  - CAP-CO-DEF-010
  - CAP-CO-REC-018
  - CAP-CO-REC-019
  - CAP-CO-REC-020
  - CAP-CO-SEC-001
  - CAP-CO-SEC-002
  - CAP-CO-SEC-003
  - CAP-CO-SEC-004
  - CAP-CO-SEC-005
  - CAP-CO-SEC-008
  - CAP-CO-SEC-009
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-platform:docs/proposals/custom-objects/09-decisions.md#D-08, D-09, D-10, D-19'
  - 'services-platform:docs/milestones/PLAT-M5-custom-records.md#D-19, PLAT-M5 D10'
  - 'services-platform:docs/milestones/plans/PLAT-M5-plan.md#PLAT-M5-S08, PLAT-M5-S14'
purpose: >-
  Record permissions and property exposure let an organization limit access to sensitive custom information.
  Each decision has a separate record or field boundary.
outcomes:
  - Record permissions and property exposure let an organization limit access to sensitive custom information.
  - Portal ownership predicates are implemented in the data layer.
actors:
  - ACT-PFM-007
  - ACT-PFM-008
  - ACT-PFM-009
  - ACT-PFM-010
surfaces:
  - console
  - api
preconditions: []
postconditions: []
permissions:
  - key: platform.custom-records.read
    where_checked: api
    scope: record
  - key: platform.custom-records.query
    where_checked: api
    scope: record
  - key: platform.custom-records.create
    where_checked: api
    scope: record
  - key: platform.custom-records.update
    where_checked: api
    scope: record
  - key: platform.custom-records.delete
    where_checked: api
    scope: record
  - key: platform.custom-records.publish
    where_checked: api
    scope: record
  - key: platform.custom-records.export
    where_checked: api
    scope: record
  - key: platform.custom-records.history
    where_checked: api
    scope: record
rules:
  - id: BR-CAP-PFM-MTD-011-01
    proved_by: [ATS-PFM-MTD-011-01, TST-PFM-MTD-051]
    statement: >-
      Shared record permissions support assignments scoped to one custom object, hiding other object records
      behind a not-found response.
    kind: permission
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/custom-objects/tests/e2e/custom-object-records.e2e.spec.js#refuses the same
      role another object’s records, answering as if the object were not there
    origin: 'services-platform:docs/proposals/custom-objects/09-decisions.md#D-09 (approved 2026-10-18)'
  - id: BR-CAP-PFM-MTD-011-02
    proved_by: [ATS-PFM-MTD-010-07, ATS-PFM-MTD-011-02, ATS-PFM-MTD-011-08, TST-PFM-MTD-014, TST-PFM-MTD-051]
    statement: >-
      Roles-only objects require an active object-specific assignment in addition to permission reach;
      built-in, workspace-wide and customer-wide grants alone do not expose them.
    kind: permission
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/custom-objects/tests/e2e/custom-object-records.e2e.spec.js#keeps a roles-only
      object from a customer-wide assignment, answering as if it were not there
    origin: >-
      services-platform:docs/milestones/PLAT-M5-custom-records.md#PLAT-M5 D10 (Andrew, 2026-10-19: "Build it
      in PLAT-M5")
  - id: BR-CAP-PFM-MTD-011-03
    proved_by: [ATS-PFM-MTD-011-03, TST-PFM-MTD-072]
    statement: >-
      Platform Administrator receives every definition and record key, User receives definition reads plus
      record read, query, create, update and history, and Read Only receives definition reads plus record
      read, query and history.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/custom-objects/tests/unit/custom-object-permission-keys.spec.ts#gives Platform
      User reading, querying, creating and updating records and their history, and reading definitions
    origin: 'services-platform:docs/proposals/custom-objects/09-decisions.md#D-09'
  - id: BR-CAP-PFM-MTD-011-04
    proved_by: [ATS-PFM-MTD-011-04, ATS-PFM-MTD-011-08, TST-PFM-MTD-072]
    statement: >-
      Record archival and restoration require the separately granted delete permission and support
      object-specific scope.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/custom-objects/tests/unit/custom-object-permission-keys.spec.ts#requires one
      key per route, each a console route, the health route public, every record route scoped to its object
    origin: 'services-platform:docs/proposals/custom-objects/09-decisions.md#D-19 (Andrew, 2026-10-18: "Delete key")'
  - id: BR-CAP-PFM-MTD-011-05
    proved_by: []
    statement: >-
      Record export is marked sensitive and reserved to administrators, but no current route requires its
      dedicated key.
    kind: permission
    enforced_at:
      - api
    must_prove: false
    provenance: test
    source: >-
      services-platform:modules/custom-objects/tests/unit/custom-object-permission-keys.spec.ts#marks
      exporting records sensitive, and no other key of the two resources
    origin: none
  - id: BR-CAP-PFM-MTD-011-06
    proved_by: [ATS-PFM-MTD-006-10, ATS-PFM-MTD-011-05, TST-PFM-MTD-073]
    statement: >-
      Audience projection shows all properties to staff, owner-or-broader properties to owners,
      portal-or-public properties to members and only public properties to anonymous readers; portal links
      exclude staff-only types.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/custom-objects/tests/unit/exposure.spec.ts#shows a portal member the portal
      and public properties
    origin: 'services-platform:docs/proposals/custom-objects/09-decisions.md#D-10 (approved 2026-10-18)'
  - id: BR-CAP-PFM-MTD-011-07
    proved_by: [ATS-PFM-MTD-011-06, TST-PFM-MTD-069]
    statement: >-
      Data-layer portal predicates combine ownership, organizational roles, links, publication and
      eligibility, exclude archived records and limit members without contacts to publication or eligibility;
      portal routes remain absent.
    kind: permission
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/custom-objects/tests/integration/services/persistence/portal-ownership-predicates.integration.spec.js#grants
      the owner the boat it owns now, and neither an ended ownership nor an archived boat
    origin: 'services-platform:docs/proposals/custom-objects/09-decisions.md#D-08 (approved 2026-10-18)'
  - id: BR-CAP-PFM-MTD-011-08
    proved_by: [ATS-PFM-MTD-011-07, TST-PFM-MTD-008]
    statement: >-
      Console action visibility follows permissions, leaving readers without edit controls and hiding
      inaccessible object navigation and cards.
    kind: permission
    enforced_at:
      - console
    must_prove: true
    provenance: test
    source: >-
      react-console:acceptance/custom-objects/playwright/journeys/PLAT-M5-S08.spec.ts#PLAT-M5-S08: a read-only
      volunteer is offered no edit actions; a person without access sees no menu and no card
    origin: 'services-platform:docs/milestones/plans/PLAT-M5-plan.md#PLAT-M5-S08'
  - id: BR-CAP-PFM-MTD-011-09
    proved_by: []
    statement: System execution without a permission slice can reach every custom object in its workspace.
    kind: permission
    enforced_at:
      - service
    must_prove: false
    provenance: documented
    source: 'services-platform:docs/custom-objects.md#18. Records: permissions and scope'
    origin: none
scenarios:
  - id: SC-CAP-PFM-MTD-011-01
    given: Enforcement Actions uses object-specific Investigators assignments.
    when: Open the console as an investigator and as unrelated staff.
    then: 'Investigators can view and edit, while unrelated staff receive no menu, card or record.'
    provenance: test
    source: >-
      react-console:acceptance/custom-objects/playwright/journeys/PLAT-M5-S14.spec.ts#PLAT-M5-S14: restricted
      to the Investigators role and granted in Security: only investigators see and edit
edge_cases:
  - id: SC-CAP-PFM-MTD-011-02
    given: Boat access rules include crew and owning-organization billing roles.
    when: Evaluate readers with current ties and an expired organizational role.
    then: The active crew and billing ties grant access while the expired role does not.
    provenance: test
    source: >-
      services-platform:modules/custom-objects/tests/integration/services/persistence/portal-ownership-predicates.integration.spec.js#grants
      nothing through owner_organization to a member whose role there has ended
constraints: []
depends_on:
  - CAP-PFM-MTD-009
related:
  - CAP-PFM-MTD-010
  - CAP-PFM-MTD-012
  - CAP-PFM-MTD-014
journeys:
  - JNY-PFM-MTD-003
open_questions: []
concepts:
  - CON-PFM-MTD-004
evidence:
  - >-
    services-platform at ad3f6a6582843008ed0f5a17b131878d15829af1: aws/platform.service.ts ,
    modules/custom-objects/services/access/record-access.ts, exposure.ts,
    services/persistence/portal-ownership-predicates.ts; tests unit/custom-object-permission-keys.spec.ts,
    unit/exposure.spec.ts, integration/services/persistence/portal-ownership-predicates.integration.spec.js,
    e2e/custom-object-records.e2e.spec.js ; docs/custom-objects.md §18 to §20.
  - >-
    react-console at baf6dae382d6f41dce976c7f848667ccc37e076f:
    components/configuration/custom-objects/access-section.tsx,
    components/console/custom-objects/object-gate.tsx; Playwright PLAT-M5-S08, S14.
controls: [TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-DAT-005, TC-IAM-003, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-005, TC-PI-003, 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]
exercised_by: [FAS-PFM-MTD-04-02, FAS-PFM-MTD-04-04]
suites: [TST-PFM-MTD-008, TST-PFM-MTD-014, TST-PFM-MTD-051, TST-PFM-MTD-069, TST-PFM-MTD-072, TST-PFM-MTD-073]
---

# Control Custom Record Audiences

## Purpose

Record permissions and property exposure let an organization limit access to sensitive custom information. Each decision has a separate record or field boundary.

## How It Works

Security assignments grant shared record permissions with optional object scope. A custom object can additionally require object-specific roles. The service checks reach before returning its records. The console uses permission information to choose available actions and navigation. Field projection narrows readable properties for the audience. Portal ownership predicates are implemented in the data layer. Portal and public routes remain deferred, so those projections do not establish a delivered portal experience.

## Relationships

Security owns role assignments. Object settings select the access mode, field rules select exposure and history checks its separate permission.
