---
id: ATS-PFM-QRY-012
scope: CAP-PFM-QRY-012
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-012-01
    title: Dashboards reject a direct single source
    level: api
    proves:
      - BR-CAP-PFM-QRY-012-01
      - INV-DOM-PFM-QRY-003-03
    preconditions: A dashboard creation request is available.
    steps: Create without a direct saved-query reference and then with one.
    expected: The source-free dashboard shape works and the direct reference returns 400.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#answers 200 to a dashboard naming no
        saved query of its own
      - >-
        services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#refuses a dashboard naming a
        saved_query_id of its own as 400
      - TST-PFM-QRY-233
    provenance: test
    source: >-
      services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#answers 200 to a dashboard naming no
      saved query of its own
    category: validation
  - id: ATS-PFM-QRY-012-02
    title: Dashboard sources follow first widget use
    level: api
    proves:
      - BR-CAP-PFM-QRY-012-02
      - INV-DOM-PFM-QRY-003-05
    preconditions: Widgets name two questions and repeat one of them.
    steps: 'Read the dashboard, change its widgets and read it again.'
    expected: 'Sources are distinct, ordered by first use and replaced with the revised layout’s dependencies.'
    negative: false
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#answers its sources once each, in
        widget order, with their names and applications
      - >-
        services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#replaces its sources with the queries
        its widgets name in a PUT
      - TST-PFM-QRY-233
    provenance: test
    source: >-
      services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#answers its sources once each, in widget
      order, with their names and applications
    category: rule
  - id: ATS-PFM-QRY-012-03
    title: Hidden widget sources fail the save
    level: api
    proves:
      - BR-CAP-PFM-QRY-012-03
    preconditions: Another person owns a private question.
    steps: Save a dashboard containing a widget for it.
    expected: The refusal locates the unavailable widget source with 400.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#refuses a widget over a saved query
        the caller may not see as 400 naming the widget at definition
      - >-
        services-platform:modules/queries/tests/integration/services/reports/report-library.integration.spec.js#refuses
        a dashboard with a widget over a colleague’s private saved query as if it did not exist, naming the
        widget
      - >-
        react-console:acceptance/reporting/playwright/journeys/dashboards-designer/RPT-ACC-0240.spec.ts#RPT-ACC-0240
      - TST-PFM-QRY-233
      - TST-PFM-QRY-335
      - TST-PFM-QRY-096
    provenance: test
    source: >-
      services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#refuses a widget over a saved query the
      caller may not see as 400 naming the widget at definition
    category: validation
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-012-04
    title: The narrowest source limits dashboard sharing
    level: api
    proves:
      - BR-CAP-PFM-QRY-012-04
    preconditions: A dashboard combines organization and selected-role questions.
    steps: Attempt organization sharing.
    expected: The conflict identifies the selected-role source.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#refuses a dashboard shared wider than
        one of its sources as 409, naming that source
      - >-
        react-console:acceptance/reporting/playwright/journeys/catalog-and-sharing/RPT-ACC-0009.spec.ts#RPT-ACC-0009
      - >-
        react-console:acceptance/reporting/playwright/journeys/dashboards-designer/RPT-ACC-0239.spec.ts#RPT-ACC-0239
      - TST-PFM-QRY-233
      - TST-PFM-QRY-054
      - TST-PFM-QRY-095
    provenance: test
    source: >-
      services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#refuses a dashboard shared wider than
      one of its sources as 409, naming that source
    category: interaction
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-012-05
    title: Widget dependencies block source removal
    level: api
    proves:
      - BR-CAP-PFM-QRY-012-05
    preconditions: One query is used by a dashboard widget.
    steps: 'Delete it, remove that dependency and try again.'
    expected: The initial deletion conflicts and the released source can then be deleted.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#refuses to delete a saved query one of
        its widgets draws on as 409 saved_query_reported
      - TST-PFM-QRY-233
    provenance: test
    source: >-
      services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#refuses to delete a saved query one of
      its widgets draws on as 409 saved_query_reported
    category: interaction
  - id: ATS-PFM-QRY-012-06
    title: Definition changes differ from renamed sources
    level: api
    proves:
      - BR-CAP-PFM-QRY-012-06
    preconditions: A dashboard uses two saved questions.
    steps: Change one definition and rename the other.
    expected: Only the definition change produces a changed-source warning.
    negative: false
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#answers saved_query_changed once one
        of its sources has been edited, naming which
      - >-
        services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#does not answer saved_query_changed
        after a source is only renamed, because its data did not change (DEF-RPT-0640)
      - TST-PFM-QRY-233
    provenance: test
    source: >-
      services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#answers saved_query_changed once one of
      its sources has been edited, naming which
    category: edge
  - id: ATS-PFM-QRY-012-07
    title: Invisible sources withhold their names
    level: api
    proves:
      - BR-CAP-PFM-QRY-012-07
      - INV-DOM-PFM-QRY-003-07
    preconditions: A source becomes private after an existing dashboard share.
    steps: Read source metadata as someone no longer in that audience.
    expected: 'Only its identity and change state are returned, without its name.'
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/reports/report-library.integration.spec.js#answers
        a reader only the id and the change of a source narrowed since the dashboard was shared
      - TST-PFM-QRY-335
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/reports/report-library.integration.spec.js#answers
      a reader only the id and the change of a source narrowed since the dashboard was shared
    category: permission
  - id: ATS-PFM-QRY-012-08
    title: Catalog visibility needs any accessible source
    level: api
    proves:
      - BR-CAP-PFM-QRY-012-08
    preconditions: A dashboard has two sources with readers able to access one or neither.
    steps: List dashboards as each reader and inspect an empty dashboard.
    expected: 'One accessible source is sufficient, none removes the populated entry, and an empty dashboard passes.'
    negative: true
    data_needs: Prepare isolated fixtures for the states described here.
    bound_to: []
    provenance: proposed
    source: 'services-platform:docs/queries/reports.md#2. Who may do what'
    category: rule
  - id: ATS-PFM-QRY-012-09
    title: Dashboard sharing does not confer data access
    level: browser
    proves:
      - BR-CAP-PFM-QRY-012-09
    preconditions: A shared dashboard has viewers with different ledger authority.
    steps: Open the dashboard under each viewer.
    expected: Figures reflect each viewer’s access and an unavailable widget fails independently.
    negative: false
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        react-console:acceptance/reporting/playwright/journeys/dashboards-designer/RPT-ACC-0241.spec.ts#RPT-ACC-0241
      - TST-PFM-QRY-097
    provenance: test
    source: >-
      react-console:acceptance/reporting/playwright/journeys/dashboards-designer/RPT-ACC-0241.spec.ts#RPT-ACC-0241
    category: permission
  - id: ATS-PFM-QRY-012-10
    title: Layout content round-trips
    level: api
    proves:
      - BR-CAP-PFM-QRY-012-10
    preconditions: A dashboard document includes filters and positioning content.
    steps: Save and reopen the document.
    expected: Its retained content matches the submitted layout.
    negative: false
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#answers the definition exactly as it
        was sent, widgets, filters and layouts untouched
      - TST-PFM-QRY-233
    provenance: test
    source: >-
      services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#answers the definition exactly as it was
      sent, widgets, filters and layouts untouched
    category: invariant
  - id: ATS-PFM-QRY-012-11
    title: A second dashboard source narrows the sharing choice
    category: interaction
    level: api
    exercises:
      - CAP-PFM-QRY-011
      - CAP-PFM-QRY-012
    proves:
      - BR-CAP-PFM-QRY-011-04
      - BR-CAP-PFM-QRY-012-04
    preconditions: An organization-shared question and a Finance-only question supply separate widgets.
    steps: 'Save a private dashboard, attempt organization sharing and then share only with Finance.'
    expected: The wider attempt identifies the Finance source; the contained audience can be saved.
    negative: false
    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/e2e/reports.e2e.spec.js#refuses a report shared wider than its
        saved query as 409 ReportSharedWiderThanQuery, naming the query
      - >-
        services-platform:modules/queries/tests/e2e/reports.e2e.spec.js#refuses a dashboard shared wider than
        one of its sources as 409, naming that source
  - id: ATS-PFM-QRY-012-12
    title: A dashboard render stops after source access is revoked
    category: interaction
    level: api
    exercises:
      - CAP-PFM-QRY-012
      - CAP-PFM-QRY-013
    proves:
      - BR-CAP-PFM-QRY-012-09
      - BR-CAP-PFM-QRY-013-06
    preconditions: A dashboard has two widgets and its requester loses one source permission between print-page requests.
    steps: >-
      Start rendering, complete a permitted source read, revoke access and let the next source request
      proceed.
    expected: The later refusal ends the export without a file containing partial data or a refusal message.
    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:docs/queries/reports.md#6. Dashboards'
      - >-
        services-platform:modules/queries/tests/integration/services/rendering/render-report.integration.spec.js#fails
        the export access_lost rather than printing a page of refusals
evidence:
  - >-
    Pinned reference:
    react-console:acceptance/reporting/playwright/journeys/catalog-and-sharing/RPT-ACC-0009.spec.ts
  - >-
    Pinned reference:
    react-console:acceptance/reporting/playwright/journeys/dashboards-designer/RPT-ACC-0239.spec.ts
  - >-
    Pinned reference:
    react-console:acceptance/reporting/playwright/journeys/dashboards-designer/RPT-ACC-0240.spec.ts
  - >-
    Pinned reference:
    react-console:acceptance/reporting/playwright/journeys/dashboards-designer/RPT-ACC-0241.spec.ts
  - 'Pinned reference: services-platform:docs/queries/reports.md'
  - 'Pinned reference: services-platform:modules/queries/tests/e2e/reports.e2e.spec.js'
  - >-
    Pinned reference:
    services-platform:modules/queries/tests/integration/services/reports/report-library.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-062'
  boundary: 'gap: FND-PFM-QRY-062'
  concurrency: 'gap: FND-PFM-QRY-062'
  invariant: covered
  interaction: covered
coverage_findings:
  - FND-PFM-QRY-062
transition_obligations: []
unproved_rules: []
---

# Combine saved questions in a dashboard: Capability Test Specification

## Coverage

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

## 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 |
|---|---|
| Journey dependency | `ATS-PFM-QRY-012-04` |
| Journey dependency | `ATS-PFM-QRY-012-05` |
| `CAP-PFM-QRY-011` | `ATS-PFM-QRY-012-11` |
| `CAP-PFM-QRY-013` | `ATS-PFM-QRY-012-12` |

## 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.
