---
id: CAP-PFM-NOT-003
title: Select eligible notification recipients
feature: FEAT-PFM-NOT-02
product_area: platform
module: notifications
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
supersedes:
  - NT-ACC-0201
  - NT-ACC-0202
  - NT-ACC-0203
  - PLAT-M23-S07
  - PLAT-M23-S08
  - PLAT-M23-S09
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-platform:docs/proposals/notifications/23-decisions.md#D-04'
  - >-
    services-platform:docs/milestones/plans/PLAT-M23-plan.humanized.md#PLAT-M23-S07
  - >-
    services-platform:docs/milestones/plans/PLAT-M23-plan.humanized.md#PLAT-M23-S08
  - >-
    services-platform:docs/milestones/plans/PLAT-M23-plan.humanized.md#PLAT-M23-S09
purpose: >-
  Platform identifies the current, eligible staff recipients from the audience
  selected by the producer.
outcomes:
  - >-
    Audience selection identifies eligible staff and records why each person
    qualifies.
  - Ineligible recipients receive no new delivery.
concepts:
  - CON-PFM-NOT-003
actors:
  - ACT-PFM-030
  - ACT-PFM-031
surfaces:
  - job
preconditions: []
postconditions: []
permissions: []
rules:
  - id: BR-CAP-PFM-NOT-003-01
    statement: >-
      Audience entries select a user, several users, a scoped responsibility, a
      role or a permission; Definitions restrict accepted types; Empty
      audiences, unknown types and resource scopes without identifiers are
      rejected, with allowed types reported for a mismatch.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/unit/audience-planner.spec.js#refuses
      a kind the definition does not accept, naming the kinds it does
    origin: none
  - id: BR-CAP-PFM-NOT-003-02
    statement: >-
      Recipients are resolved during processing rather than publication; a
      responsibility transferred before dispatch therefore reaches its current
      holder.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/resolve-audience.integration.spec.js#changes
      the people when the responsibility is reassigned between the publish and
      the dispatch
    origin: 'services-platform:docs/proposals/notifications/23-decisions.md#D-04'
  - id: BR-CAP-PFM-NOT-003-03
    statement: >-
      Responsibility lookup supplies current holders, delegates and applicable
      fallback holders along the requested scope chain; Holding the
      responsibility in another unit does not qualify a person for this scope.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/resolve-audience.integration.spec.js#is
      the holders of that unit and not the holder of another unit
    origin: >-
      services-platform:docs/milestones/plans/PLAT-M23-plan.humanized.md#PLAT-M23-S07
  - id: BR-CAP-PFM-NOT-003-04
    statement: >-
      Roles select their active workspace members; permissions select people
      with active roles granting the permission under authorizer matching;
      missing roles and ungranted permissions yield no recipients.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/resolve-audience.integration.spec.js#is
      the people whose active roles grant it, compared as the authorizer does
    origin: none
  - id: BR-CAP-PFM-NOT-003-05
    statement: >-
      Recipients form a deduplicated union sorted by user identifier; Producer
      exclusions and the actor are removed unless actor inclusion is requested.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/unit/audience-planner.spec.js#leaves
      out the actor, who is not told of their own act
    origin: none
  - id: BR-CAP-PFM-NOT-003-06
    statement: >-
      After exclusions and actor removal, an audience over two hundred is
      rejected in full; an audience of exactly two hundred is allowed.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/unit/audience-planner.spec.js#refuses
      201 people as a whole, selecting nobody
    origin: 'services-platform:docs/proposals/notifications/23-decisions.md#D-04'
  - id: BR-CAP-PFM-NOT-003-07
    statement: >-
      Eligible recipients are active console users belonging to the workspace's
      customer; other customers' users, pending invitees and portal users are
      removed and recorded as isolation refusals.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/orchestrate-request.integration.spec.js#drops
      a user of another customer, an invited user and a portal user, recording
      isolation_refused
    origin: none
  - id: BR-CAP-PFM-NOT-003-08
    statement: >-
      A resolved empty audience finishes as no recipients without producing
      notices, including when isolation removes every candidate.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/orchestrate-request.integration.spec.js#notifies
      nobody when everyone named is outside the organization, recording
      no_recipients with the refusal
    origin: none
scenarios:
  - id: SC-CAP-PFM-NOT-003-01
    given: >-
      Jane holds Northeast Batch posting and has delegated cover to Sam for a
      week.
    when: The producer selects responsibility holders at Northeast.
    then: >-
      Jane qualifies as holder and Sam as delegate; another unit's holder is
      excluded.
    provenance: test
    source: >-
      services-platform:modules/notifications/tests/integration/services/orchestration/resolve-audience.integration.spec.js#is
      the delegates of that unit’s holders too, worded as covering the
      responsibility
  - id: SC-CAP-PFM-NOT-003-02
    given: An audience selects a user belonging to a different customer.
    when: Platform evaluates the request.
    then: No eligible recipient remains and History retains the isolation refusal.
    provenance: test
    source: >-
      react-console:acceptance/notifications/playwright/journeys/pipeline/NT-ACC-0202.spec.ts#NT-ACC-0202
edge_cases: []
constraints: []
depends_on:
  - CAP-PFM-NOT-002
related:
  - CAP-PFM-NOT-010
  - CAP-PFM-NOT-011
  - CAP-PFM-NOT-014
journeys:
  - JNY-PFM-NOT-003
  - JNY-PFM-NOT-005
open_questions: []
evidence:
  - >-
    Pinned evidence inventory 1:
    services-platform:docs/proposals/notifications/23-decisions.md;
    services-platform:modules/notifications/tests/unit/audience-planner.spec.js;
    services-platform:docs/milestones/PLAT-M23-notifications-core-and-in-app.md;
    react-console:acceptance/notifications/playwright/journeys/pipeline/NT-ACC-0202.spec.ts
  - >-
    Pinned evidence inventory 2:
    services-platform:docs/milestones/plans/PLAT-M23-plan.humanized.md;
    services-platform:modules/notifications/tests/integration/services/orchestration/resolve-audience.integration.spec.js;
    services-platform:modules/notifications/tests/integration/services/orchestration/orchestrate-request.integration.spec.js
controls: [TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-002, 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]
---

# Select eligible notification recipients

## Purpose

Platform identifies the current, eligible staff recipients from the audience selected by the producer.

## How It Works

A producer selects audience entries permitted by the definition. Platform evaluates them when dispatch processes the request. Responsibility lookup contributes current holders, delegates and fallback selections. Role and permission lookup contributes active staff members. Platform unions the results and removes excluded users and, normally, the actor. The recipient limit is checked before eligibility filtering. Customer membership and console-account eligibility prevent cross-customer delivery. Empty and invalid outcomes remain visible even when no notice is created.

The rule rows define this outcome; the acceptance set identifies existing proof and proposed checks. Implementation evidence alone does not approve the observed details.

## Relationships

Committed publication supplies the requests processed by this outcome.
