---
id: ATS-PFM-QRY-009
scope: CAP-PFM-QRY-009
product_area: platform
module: queries
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
  rhythm-v2-docs: 99376625d3e7ac26936413cfc31a88fba6562464
scenarios:
  - id: ATS-PFM-QRY-009-01
    title: Views require a valid recipe anchor
    level: api
    proves:
      - BR-CAP-PFM-QRY-009-01
    preconditions: A live contact recipe is registered.
    steps: 'Save with no recipe, an unknown recipe, a conflicting dataset and an omitted dataset.'
    expected: Invalid anchors return 400; omission resolves to the recipe’s dataset.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a body naming no
        recipe as 400
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a recipe nobody
        has registered as 400
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a body whose
        dataset is not the recipe’s as 400
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#saves a body naming no
        dataset, because the recipe decides it
      - TST-PFM-QRY-210
    provenance: test
    source: >-
      services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a body naming no
      recipe as 400
    category: validation
  - id: ATS-PFM-QRY-009-02
    title: Repeating joins cannot anchor record lists
    level: api
    proves:
      - BR-CAP-PFM-QRY-009-02
      - INV-DOM-PFM-QRY-002-09
    preconditions: A recipe includes a one-to-many join that repeats records.
    steps: Use it as an Explorer view anchor.
    expected: The rejection identifies the incompatible join.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/explorer/tests/integration/services/definitions/recipe-anchors.integration.spec.js#refuses
        a recipe whose joins answer a base record once per child
      - >-
        services-platform:modules/explorer/tests/integration/services/definitions/recipe-anchors.integration.spec.js#says
        which join breaks the grain, so the recipe’s owner can repair it
      - TST-PFM-QRY-211
    provenance: test
    source: >-
      services-platform:modules/explorer/tests/integration/services/definitions/recipe-anchors.integration.spec.js#refuses
      a recipe whose joins answer a base record once per child
    category: validation
  - id: ATS-PFM-QRY-009-03
    title: View definitions use the anchored model
    level: api
    proves:
      - BR-CAP-PFM-QRY-009-03
    preconditions: Plain and joined recipes are available.
    steps: 'Save unknown fields, absent joined instances and an invalid patch field.'
    expected: Every unsupported selection is rejected at its location.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a definition
        naming a field the dataset has not got as 400
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a joined column of
        an instance the recipe does not join as 400
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a patch that names
        a field the dataset has not got as 400
      - TST-PFM-QRY-210
    provenance: test
    source: >-
      services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a definition naming
      a field the dataset has not got as 400
    category: validation
  - id: ATS-PFM-QRY-009-04
    title: Retired anchors remain repairable
    level: api
    proves:
      - BR-CAP-PFM-QRY-009-04
    preconditions: A retained view’s recipe has retired.
    steps: Read the view.
    expected: It returns the recipe-missing problem rather than refusing the entire read.
    negative: false
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/explorer/tests/integration/services/definitions/recipe-anchors.integration.spec.js#answers
        recipe_missing for a recipe that has gone, rather than an error
      - >-
        services-platform:modules/explorer/tests/integration/services/definitions/recipe-anchors.integration.spec.js#answers
        recipe_missing for a recipe that no longer answers one row per record
      - TST-PFM-QRY-211
    provenance: test
    source: >-
      services-platform:modules/explorer/tests/integration/services/definitions/recipe-anchors.integration.spec.js#answers
      recipe_missing for a recipe that has gone, rather than an error
    category: edge
  - id: ATS-PFM-QRY-009-05
    title: Colleagues see shared views without owner powers
    level: api
    proves:
      - BR-CAP-PFM-QRY-009-05
    preconditions: Both private and shared views belong to another person.
    steps: Read and list them as a colleague.
    expected: The private entry is missing; the shared entry is visible without edit power.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#answers 404, not 403, for
        another person’s private view
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#answers a colleague a view
        shared with the tenant
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#tells a colleague they may
        not edit a shared view that is not theirs
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#leaves out another
        person’s private view
      - TST-PFM-QRY-210
    provenance: test
    source: >-
      services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#answers 404, not 403, for
      another person’s private view
    category: permission
  - id: ATS-PFM-QRY-009-06
    title: View sharing and administration remain distinct
    level: api
    proves:
      - BR-CAP-PFM-QRY-009-06
    preconditions: Callers differ in share and manage grants.
    steps: 'Share without authority, edit another shared view as a colleague and manager, and replace its dataset.'
    expected: 'Unauthorized writes fail, manager maintenance works and dataset change is refused.'
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses sharing a view
        without the share permission as 403
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a colleague
        replacing a shared view as 403
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#allows an administrator to
        replace a shared view they do not own
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a replacement that
        changes the dataset as 400
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#is granted the power to
        share, because that is a user-tier key
      - TST-PFM-QRY-210
    provenance: test
    source: >-
      services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses sharing a view
      without the share permission as 403
    category: permission
  - id: ATS-PFM-QRY-009-07
    title: Joined-dataset access applies to every view operation
    level: api
    proves:
      - BR-CAP-PFM-QRY-009-07
    preconditions: The caller lacks access to a recipe’s joined dataset.
    steps: 'Create, list and read views using the recipe.'
    expected: Each request returns 403.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a joined recipe to
        a caller who may not query a dataset it joins to, as 403
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a caller who may
        not query the dataset as 403
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a caller who may
        not query the recipe’s dataset a view they can otherwise see, as 403
      - TST-PFM-QRY-210
    provenance: test
    source: >-
      services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a joined recipe to a
      caller who may not query a dataset it joins to, as 403
    category: permission
  - id: ATS-PFM-QRY-009-08
    title: View counts and names respect their bounds
    level: api
    proves:
      - BR-CAP-PFM-QRY-009-08
    preconditions: One workspace already has two hundred views for a dataset.
    steps: 'Create another, reuse the idea elsewhere and try blank or oversized names.'
    expected: The cap and invalid names are refused while another workspace remains independent.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/explorer/tests/integration/services/persistence/explorer-views.integration.spec.js#refuses
        the next view of that dataset
      - >-
        services-platform:modules/explorer/tests/integration/services/persistence/explorer-views.integration.spec.js#counts
        the limit per tenant, so another tenant may still save one
      - >-
        services-platform:modules/explorer/tests/integration/services/persistence/explorer-views.integration.spec.js#refuses
        a blank name
      - >-
        services-platform:modules/explorer/tests/integration/services/persistence/explorer-views.integration.spec.js#refuses
        a name longer than 120 characters
      - TST-PFM-QRY-218
    provenance: test
    source: >-
      services-platform:modules/explorer/tests/integration/services/persistence/explorer-views.integration.spec.js#refuses
      the next view of that dataset
    category: boundary
  - id: ATS-PFM-QRY-009-09
    title: Team references remain unsupported
    level: api
    proves:
      - BR-CAP-PFM-QRY-009-09
    preconditions: A proposed view includes a team reference.
    steps: Save the proposed view.
    expected: The response returns 400.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a team id, which
        is reserved, as 400
      - >-
        services-platform:modules/explorer/tests/integration/services/persistence/explorer-views.integration.spec.js#refuses
        a view that names a team
      - TST-PFM-QRY-210
      - TST-PFM-QRY-218
    provenance: test
    source: >-
      services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a team id, which is
      reserved, as 400
    category: validation
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-009-10
    title: View replacement protects concurrent edits
    level: api
    proves:
      - BR-CAP-PFM-QRY-009-10
    preconditions: A view is currently at version two.
    steps: Replace using its earlier version and without any version.
    expected: Requests return 409 and 400 without changing the stored view.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a stale version as
        409
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a replacement that
        states no version as 400 MissingVersion, never as a server fault
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#leaves the view unchanged
        after refusing a replacement with no version
      - TST-PFM-QRY-210
    provenance: test
    source: >-
      services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a stale version as
      409
    category: concurrency
  - id: ATS-PFM-QRY-009-11
    title: Personal preferences retain their version and references
    level: api
    proves:
      - BR-CAP-PFM-QRY-009-11
    preconditions: Two people use the same Explorer without prior preferences.
    steps: 'Read defaults, save at zero, omit a later version, exceed twenty pins and retain a deleted reference.'
    expected: Defaults and valid saves work; stale and oversized saves fail; the unvalidated reference remains stored.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-preferences-api.e2e.spec.js#answers the whole
        default arrangement: whose it is, which Explorer, nothing pinned and version zero
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-preferences-api.e2e.spec.js#saves a first
        arrangement at If-Match 0, the version the defaults were answered at (DEF-CRM-0391)
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-preferences-api.e2e.spec.js#refuses a later save
        that states no version as 409, so nothing is overwritten unread
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-preferences-api.e2e.spec.js#refuses more pinned
        views than an Explorer may hold as 400
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-preferences-api.e2e.spec.js#answers such an id
        back on the read that follows, rather than refusing the whole arrangement
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-preferences-api.e2e.spec.js#answers each person
        their own arrangement of the same Explorer
      - TST-PFM-QRY-209
    provenance: test
    source: >-
      services-platform:modules/explorer/tests/e2e/explorer-preferences-api.e2e.spec.js#answers the whole
      default arrangement: whose it is, which Explorer, nothing pinned and version zero
    category: rule
  - id: ATS-PFM-QRY-009-12
    title: A retired recipe leaves a view repairable
    category: interaction
    level: api
    exercises:
      - CAP-PFM-QRY-008
      - CAP-PFM-QRY-009
    proves:
      - BR-CAP-PFM-QRY-008-09
      - BR-CAP-PFM-QRY-009-04
    preconditions: A person retains a contact view anchored to an active recipe.
    steps: 'Release a manifest without the recipe, read the retained view and try saving it again.'
    expected: The read identifies the missing anchor; a new save is refused until the recipe becomes valid again.
    negative: true
    data_needs: >-
      Use an isolated workspace with the described source records, access grants and a surviving control
      workspace.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-platform:modules/queries/tests/integration/services/recipe-registration/register-query-recipes.integration.spec.js#retires
        a recipe the manifest no longer declares, and leaves the rest alone
      - >-
        services-platform:modules/explorer/tests/integration/services/definitions/recipe-anchors.integration.spec.js#answers
        recipe_missing for a recipe that has gone, rather than an error
  - id: ATS-PFM-QRY-009-13
    title: Renewing navigation checks the view’s data access again
    category: interaction
    level: api
    exercises:
      - CAP-PFM-QRY-009
      - CAP-PFM-QRY-010
    proves:
      - BR-CAP-PFM-QRY-009-07
      - BR-CAP-PFM-QRY-010-05
    preconditions: A recipe-anchored list has a navigation session and the owner loses base-dataset access.
    steps: 'Read a retained identity, then move beyond the retained window and request whole-result selection.'
    expected: Retained return state remains available; renewal and selection fail the current dataset access check.
    negative: true
    data_needs: >-
      Use an isolated workspace with the described source records, access grants and a surviving control
      workspace.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js#refuses a joined recipe to
        a caller who may not query a dataset it joins to, as 403
      - 'services-platform:modules/explorer/services/navigation/navigation-sessions.ts:extendForward'
evidence:
  - 'Pinned reference: services-platform:modules/explorer/tests/e2e/explorer-preferences-api.e2e.spec.js'
  - 'Pinned reference: services-platform:modules/explorer/tests/e2e/explorer-views-api.e2e.spec.js'
  - >-
    Pinned reference:
    services-platform:modules/explorer/tests/integration/services/definitions/recipe-anchors.integration.spec.js
  - >-
    Pinned reference:
    services-platform:modules/explorer/tests/integration/services/persistence/explorer-views.integration.spec.js
coverage_notes:
  transition: >-
    This capability has no formal lifecycle of its own. Audience and definition changes remain rule,
    permission and concurrency proofs; related lifecycles are exercised through interaction scenarios.
coverage:
  rule: covered
  transition: not-applicable
  validation: covered
  permission: covered
  edge: covered
  failure: 'gap: FND-PFM-QRY-059'
  boundary: covered
  concurrency: covered
  invariant: 'gap: FND-PFM-QRY-059'
  interaction: covered
coverage_findings:
  - FND-PFM-QRY-059
transition_obligations: []
unproved_rules: []
---

# Organize reusable views of record lists: Capability Test Specification

## Coverage

| Rule | Scenario or Finding |
|---|---|
| `BR-CAP-PFM-QRY-009-01` | `ATS-PFM-QRY-009-01` |
| `BR-CAP-PFM-QRY-009-02` | `ATS-PFM-QRY-009-02` |
| `BR-CAP-PFM-QRY-009-03` | `ATS-PFM-QRY-009-03` |
| `BR-CAP-PFM-QRY-009-04` | `ATS-PFM-QRY-009-04`, `ATS-PFM-QRY-009-12` |
| `BR-CAP-PFM-QRY-009-05` | `ATS-PFM-QRY-009-05` |
| `BR-CAP-PFM-QRY-009-06` | `ATS-PFM-QRY-009-06` |
| `BR-CAP-PFM-QRY-009-07` | `ATS-PFM-QRY-009-07`, `ATS-PFM-QRY-009-13` |
| `BR-CAP-PFM-QRY-009-08` | `ATS-PFM-QRY-009-08` |
| `BR-CAP-PFM-QRY-009-09` | `ATS-PFM-QRY-009-09` |
| `BR-CAP-PFM-QRY-009-10` | `ATS-PFM-QRY-009-10` |
| `BR-CAP-PFM-QRY-009-11` | `ATS-PFM-QRY-009-11` |

## Interactions With Related Capabilities

The combined examples change a source, its audience or its retained state before checking the dependent outcome. Unbound examples remain proposed, and the coverage finding retains design obligations that these examples do not establish.

| Related Capability | Scenario |
|---|---|
| `CAP-PFM-QRY-008` | `ATS-PFM-QRY-009-12` |
| `CAP-PFM-QRY-010` | `ATS-PFM-QRY-009-13` |

## Evidence and Binding Limits

The source revisions pin the inspected assertions. A test binding identifies written assertions, and does not establish a successful run or approval of the expected behavior.
