---
id: TST-PFM-NOT-069
title: notifications
kind: api-lifecycle
product_area: platform
module: notifications
revision: 1
status: draft
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
repository: services-platform
files:
  - modules/notifications/tests/e2e/notifications.e2e.spec.js
implements:
  - ATS-PFM-NOT-001-11
  - ATS-PFM-NOT-002-05
  - ATS-PFM-NOT-002-06
  - ATS-PFM-NOT-002-07
  - ATS-PFM-NOT-009-01
  - ATS-PFM-NOT-009-02
  - ATS-PFM-NOT-009-03
  - ATS-PFM-NOT-009-04
  - ATS-PFM-NOT-009-05
  - ATS-PFM-NOT-009-06
  - ATS-PFM-NOT-009-07
  - ATS-PFM-NOT-010-01
  - ATS-PFM-NOT-011-01
  - ATS-PFM-NOT-011-02
  - ATS-PFM-NOT-011-03
  - ATS-PFM-NOT-011-04
  - ATS-PFM-NOT-011-05
  - ATS-PFM-NOT-012-01
  - ATS-PFM-NOT-012-02
  - ATS-PFM-NOT-012-03
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 5
isolation: >-
  Suite-owned records in the prepared integration workspaces; seeded workspace
  identities remain shared fixtures.
assertion_bindings:
  - scenario: ATS-PFM-NOT-001-11
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#lists
        the registry across applications for staff
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#refuses
        the system door and Rhythm HQ’s routes to a console caller, even one
        holding every platform key
  - scenario: ATS-PFM-NOT-002-05
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#refuses
        a malformed envelope with a 400 and an unknown field with a 400
  - scenario: ATS-PFM-NOT-002-06
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#refuses
        the system door and Rhythm HQ’s routes to a console caller, even one
        holding every platform key
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#writes
        the publish and answers the receipt, which the pipeline then turns into
        a notification
  - scenario: ATS-PFM-NOT-002-07
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#answers
        a cancel of an unknown request 404 and one without a reason 400
  - scenario: ATS-PFM-NOT-009-01
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#refuses
        every own-notification route to a caller without
        platform.notifications.use
  - scenario: ATS-PFM-NOT-009-02
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#finds
        nothing of another person’s notification, whoever asks
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#refuses
        a portal account every own-notification route, the portal being held
  - scenario: ATS-PFM-NOT-009-03
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#filters
        by unread, category and since, and pages by keyset
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#lists
        the archived by their own filter and leaves them out of the default list
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#refuses
        a bad filter, cursor or page size with a 400 naming the parameter
  - scenario: ATS-PFM-NOT-009-04
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#counts
        the unread in the summary
  - scenario: ATS-PFM-NOT-009-05
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#marks
        one read and unread, archives and unarchives it, answering it each time
  - scenario: ATS-PFM-NOT-009-06
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#marks
        everything read, optionally before an instant, answering how many
  - scenario: ATS-PFM-NOT-009-07
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#puts
        a test notification in the caller’s own list, through the whole
        pipeline, and nobody else’s
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#sends
        the default message when none is given
  - scenario: ATS-PFM-NOT-010-01
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#reads
        one of its own with its why, and nobody else’s
  - scenario: ATS-PFM-NOT-011-01
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#refuses
        History and the chain to a caller with only platform.notifications.use
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#leaves
        the list to an administrator, not to a caller who only reads their own
  - scenario: ATS-PFM-NOT-011-02
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#lists
        every person’s notifications with the person, and narrows by filters
  - scenario: ATS-PFM-NOT-011-03
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#lists
        a request that dropped a named person, one that was refused as invalid
        and one that was heard, and no other tenant’s
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#narrows
        by outcome, definition and since, newest first, and pages by keyset
  - scenario: ATS-PFM-NOT-011-04
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#reads
        the request, the notification with its why and the delivery with its
        chain
  - scenario: ATS-PFM-NOT-011-05
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#finds
        nothing for an id that is nobody’s
  - scenario: ATS-PFM-NOT-012-01
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#refuses
        the system door and Rhythm HQ’s routes to a console caller, even one
        holding every platform key
  - scenario: ATS-PFM-NOT-012-02
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#refuses
        a tenant’s requests for Rhythm HQ without an access grant into the
        tenant, as its History is
  - scenario: ATS-PFM-NOT-012-03
    suite: TST-PFM-NOT-069
    assertions:
      - >-
        services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js#lists
        the dead deliveries and refuses to retry one that is not there
evidence:
  - 'services-platform:modules/notifications/tests/e2e/notifications.e2e.spec.js'
  - The file and referenced assertion titles exist at the pinned commit.
dependency_evidence:
  - >-
    Real: the dispatcher and its authorization against signed security contexts,
    the routes, mappers, centre reads, orchestrator
  - >-
    and persistence services, and PostgreSQL with row-level security on.
    Doubled: the signer stands in for the authorizer's key, and
  - >-
    the queue between the dispatcher and the orchestrator is a recorder. Never
    doubled: the database, the permission evaluation or
---

# notifications

## Verification Boundary

This suite exercises the local services and prepared PostgreSQL database. API lifecycle cases use signed test contexts through the real route handler; they do not invoke the deployed gateway.

## What This Suite Proves

Its cases exercise restrict global catalog access to HQ; reject invalid envelopes before insertion; require system publication access; require a known cancellation target and reason; require personal notification permission; confine personal operations to the signed-in user.

The registered scenario bindings identify the assertions this executable file contributes. They retain individual test references so that a composite scenario does not become a claim of complete execution by one file.

## What It Does Not Prove

Local outcomes do not prove deployed queues, external provider acceptance, production credentials or complete browser behavior. No fresh execution or conformance result is claimed.

## Real Dependencies and Test Doubles

The notification fixtures use real PostgreSQL and module logic. Queue publication, visibility changes, nudges and installed channel adapters are recorded at their seams when the suite needs them. Signed API contexts replace the authorizer key in API suites.

## Must Not Be Doubled

Database constraints, workspace policy, state guards and the service operation under test must remain real. Recording a provider or queue call must not replace the submission, claim or outcome logic being checked.
