---
id: ATS-PFM-QRY-015
scope: CAP-PFM-QRY-015
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-015-01
    title: Schedule discovery follows owner or manager access
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-01
    preconditions: 'A schedule has owner, manager and unrelated use-holder contexts.'
    steps: 'List and read as each, narrow a manager list to mine and request another workspace.'
    expected: >-
      Permitted audiences succeed, unrelated contexts receive 404 or no entry, and mine narrows the manager
      list.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#answers
        the owner and a manager
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#answers
        a colleague holding only .use 404, as for one that does not exist
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#lists
        it for its owner and a manager, not for a colleague
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#narrows
        a manager’s list to their own with mine=1
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
        a caller with neither schedules key (403)
      - 'react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0432.spec.ts#RPT-ACC-0432'
      - TST-PFM-QRY-349
      - TST-PFM-QRY-147
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#answers
      the owner and a manager
    category: permission
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-015-02
    title: Invalid scheduling inputs write nothing
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-02
    preconditions: A source asks for a value and the caller can otherwise schedule.
    steps: >-
      Omit input, use an unpublished template, run too frequently, send invalid naming and deny dataset
      access.
    expected: 'Shape and scheduling errors return 400, data denial returns 403, and no schedule is created.'
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
        a query whose required value is missing (400, naming it)
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
        a template that has never been published (400)
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
        a schedule more often than hourly (400)
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
        a definition written in camelCase (400), and writes nothing
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
        a caller who may not read the dataset (403)
      - TST-PFM-QRY-349
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
      a query whose required value is missing (400, naming it)
    category: validation
  - id: ATS-PFM-QRY-015-03
    title: Query schedules adopt changes only on refresh
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-03
      - INV-DOM-PFM-QRY-004-07
    preconditions: A schedule’s saved source is edited after scheduling.
    steps: 'Read its warning and comparison, then explicitly refresh its pinned source.'
    expected: Both versions are visible before refresh and the updated copy clears the warning.
    negative: false
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#flags
        the saved query as changed since the schedule was set up
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#summarises
        the pinned and the latest definitions side by side
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#re-pins
        to the latest definition and clears the flag
      - TST-PFM-QRY-349
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#flags
      the saved query as changed since the schedule was set up
    category: interaction
  - id: ATS-PFM-QRY-015-04
    title: Automatic delivery rebuilds owner authority
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-04
    preconditions: An owner loses data access and a staff owner’s workspace grant later ends.
    steps: Run deliveries before and after loss.
    expected: 'Allowed work can complete, but lost access fails without messages and pauses the schedule.'
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#fails
        the run with the sentence D4 gives, and sends nothing
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#fails
        the export access_lost
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#pauses
        the schedule with the reason, on the first such run
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#runs
        while the grant is active: the run succeeds, the export holds the rows and the e-mail is asked for
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#pauses
        the schedule with the reason once the grant is ended
      - TST-PFM-QRY-350
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#fails
      the run with the sentence D4 gives, and sends nothing
    category: permission
  - id: ATS-PFM-QRY-015-05
    title: Taking responsibility requires management
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-05
    preconditions: A schedule belongs to another user.
    steps: Take ownership as a use-holder and then a manager.
    expected: The use-holder receives 403 and the manager becomes owner.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
        take-ownership to a holder of .use alone (403)
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#makes
        a manager the owner
      - 'react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0425.spec.ts#RPT-ACC-0425'
      - TST-PFM-QRY-349
      - TST-PFM-QRY-140
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
      take-ownership to a holder of .use alone (403)
    category: permission
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-015-06
    title: Run Now uses the initiating person
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-06
    preconditions: A manager runs another owner’s schedule immediately.
    steps: Queue the run and inspect its execution and history.
    expected: The manager is the execution identity and existing recipients receive the run.
    negative: false
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#answers
        the run queued, run now by the caller rather than the owner
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#is
        run by the consumer, as the caller, to the schedule’s recipients
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#shows
        the run in the history: run-now, who ran it, the file and each delivery
      - 'react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0437.spec.ts#RPT-ACC-0437'
      - TST-PFM-QRY-349
      - TST-PFM-QRY-151
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#answers
      the run queued, run now by the caller rather than the owner
    category: rule
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-015-07
    title: Recipients need valid users or outside authority
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-07
      - INV-DOM-PFM-QRY-004-06
    preconditions: A creator lacks outside-recipient permission and recipients include removed or suspended users.
    steps: Add outside and organizational addresses and execute delivery.
    expected: >-
      External admission fails without authority; organizational addresses work and unavailable users are
      skipped with reasons.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
        an outside address without platform.query-schedules.external-recipients (403), and writes nothing
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#accepts
        the address of one of the organization’s own users without it
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#records
        every recipient’s delivery: two submitted, the removed and the suspended user skipped with why
      - 'react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0428.spec.ts#RPT-ACC-0428'
      - TST-PFM-QRY-349
      - TST-PFM-QRY-350
      - TST-PFM-QRY-143
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
      an outside address without platform.query-schedules.external-recipients (403), and writes nothing
    category: permission
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-015-08
    title: Delivery retry does not repeat messages
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-08
      - INV-DOM-PFM-QRY-004-05
    preconditions: A run has two eligible recipients.
    steps: Process it twice and redeliver its completed queue message.
    expected: >-
      Only the original two recipient-keyed communications requests exist, each with an expiring personal
      link.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#asks
        for one e-mail per deliverable recipient, each under the key <run id>:<recipient id>
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#gives
        each recipient a personal link, signed for the export and that recipient, for seven days
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#submits
        nothing new when the same run is run again
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#does
        nothing for a redelivered message of the finished run
      - TST-PFM-QRY-350
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#asks
      for one e-mail per deliverable recipient, each under the key <run id>:<recipient id>
    category: invariant
  - id: ATS-PFM-QRY-015-09
    title: Empty-result behaviour depends on schedule kind
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-09
    preconditions: A query result is empty and a report schedule is proposed.
    steps: Run the empty query schedule and enable skip-empty for the report.
    expected: The query run skips messaging and the report option is refused.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#ends
        a skip-when-empty run skipped, its export holding no rows
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#sends
        no e-mail for it, and does send one for the schedule that sends empty results
      - 'services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#refuses skip-when-empty (400)'
      - TST-PFM-QRY-350
      - TST-PFM-QRY-230
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#ends
      a skip-when-empty run skipped, its export holding no rows
    category: edge
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-015-10
    title: Scheduled dates resolve anew
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-10
    preconditions: A stored date input represents today.
    steps: Run on two different workspace days.
    expected: Each export records and uses its own execution day.
    negative: false
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#runs
        the criterion on the day of each run, in the tenant’s zone
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#records
        on each run’s export the day its parameter took
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#accepts
        a date parameter as today, the relative day each run reads as its own date
      - TST-PFM-QRY-350
      - TST-PFM-QRY-349
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#runs
      the criterion on the day of each run, in the tenant’s zone
    category: boundary
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-015-11
    title: Retry and repeated-failure policies remain distinct
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-11
    preconditions: Controlled runs include transient and terminal errors followed by consecutive failures.
    steps: Process retries and the fifth failed run.
    expected: 'Transient work can recover, terminal errors are not retried and repeated failure pauses with a reason.'
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#succeeds
        on the redelivery, on its second attempt
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#e-mails
        each recipient once in all, and builds the file once
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#pauses
        the schedule after the fifth, saying why
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#fails
        each of those runs without retrying it
      - 'react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0436.spec.ts#RPT-ACC-0436'
      - TST-PFM-QRY-350
      - TST-PFM-QRY-150
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#succeeds
      on the redelivery, on its second attempt
    category: failure
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-015-12
    title: Report schedules keep report-specific formats and kind
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-12
    preconditions: 'A table report, dashboard and caller without report use are available.'
    steps: Create schedules with supported and unsupported formats and attempt a kind change.
    expected: 'Eligible Excel succeeds; invalid formats, absent access and kind replacement are refused.'
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#accepts Excel for a table
        report
      - >-
        services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#refuses Excel for a dashboard
        (400 at options.format)
      - 'services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#refuses a CSV (400)'
      - >-
        services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#refuses a caller without
        platform.reports.use (403)
      - >-
        services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#refuses a replacement that
        would turn it into a query schedule (400)
      - TST-PFM-QRY-230
    provenance: test
    source: 'services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#accepts Excel for a table report'
    category: validation
  - id: ATS-PFM-QRY-015-13
    title: Deleted-report schedules preserve only their history
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-13
    preconditions: A report has an associated schedule.
    steps: Remove the report and request resumption and immediate execution.
    expected: 'The schedule is paused for deletion, resumption returns 400 and immediate execution returns 404.'
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#pauses the schedule
        report_deleted, its report gone
      - 'services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#refuses to resume it (400)'
      - 'services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#refuses to run it now (404)'
      - 'react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0427.spec.ts#RPT-ACC-0427'
      - TST-PFM-QRY-230
      - TST-PFM-QRY-142
    provenance: test
    source: >-
      services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#pauses the schedule
      report_deleted, its report gone
    category: transition
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-015-14
    title: Imported schedules wait for legacy shutdown
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-14
    preconditions: A migrated schedule is paused and marked imported.
    steps: Resume without and then with the shutdown confirmation.
    expected: The first attempt explains the refusal and the confirmed attempt resumes.
    negative: true
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#arrives
        paused and flagged imported, owned by the person named
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
        a resume without confirmLegacyDisabled (400), saying why
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#resumes
        with it
      - TST-PFM-QRY-349
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#arrives
      paused and flagged imported, owned by the person named
    category: transition
  - id: ATS-PFM-QRY-015-15
    title: Schedule versions and copying preserve responsibility
    level: api
    proves:
      - BR-CAP-PFM-QRY-015-15
    preconditions: A schedule has a current version.
    steps: 'Replace at an older version, duplicate it and delete it.'
    expected: >-
      The stale write conflicts, the copy is paused and caller-owned, and the removed schedule is then
      missing.
    negative: false
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
        a replacement at a stale version (409)
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#duplicates
        it paused, named a copy, owned by the caller
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#deletes
        the schedule, which is then not found
      - 'react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0424.spec.ts#RPT-ACC-0424'
      - TST-PFM-QRY-349
      - TST-PFM-QRY-139
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#refuses
      a replacement at a stale version (409)
    category: concurrency
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-015-16
    title: Delivery responsibility can recover after lost access
    level: browser
    proves:
      - AS-JNY-PFM-QRY-004-01
      - AS-JNY-PFM-QRY-004-02
      - AS-JNY-PFM-QRY-004-03
    preconditions: A report schedule sends to two recipients.
    steps: Run the responsibility-transfer browser journey.
    expected: >-
      Initial delivery succeeds, source loss pauses without sending, and administrator takeover permits later
      delivery.
    negative: false
    data_needs: Use the existing binding’s controlled fixture data.
    bound_to:
      - 'react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0425.spec.ts#RPT-ACC-0425'
      - >-
        react-console:acceptance/reporting/playwright/journeys/print-and-export/RPT-ACC-0358.spec.ts#RPT-ACC-0358
      - TST-PFM-QRY-140
      - TST-PFM-QRY-118
    provenance: test
    source: 'react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0425.spec.ts#RPT-ACC-0425'
    category: interaction
    binding_note: >-
      The cited suites contribute separate assertions. The complete combined example is not a single
      executable journey.
  - id: ATS-PFM-QRY-015-17
    title: Scheduling protects the retained source until removed
    category: interaction
    level: api
    exercises:
      - CAP-PFM-QRY-006
      - CAP-PFM-QRY-015
    proves:
      - BR-CAP-PFM-QRY-006-14
      - BR-CAP-PFM-QRY-015-03
    preconditions: A saved contact question has an enabled query schedule.
    steps: 'Edit the question, compare the schedule, attempt query deletion, then delete the schedule and try again.'
    expected: >-
      The schedule keeps its earlier copy and exposes the change; deletion succeeds only after the dependency
      is removed.
    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 to delete a saved query a
        report presents as 409 saved_query_reported
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js#flags
        the saved query as changed since the schedule was set up
  - id: ATS-PFM-QRY-015-18
    title: Deleting a report pauses its recurring deliveries
    category: interaction
    level: api
    exercises:
      - CAP-PFM-QRY-011
      - CAP-PFM-QRY-015
    proves:
      - BR-CAP-PFM-QRY-011-12
      - BR-CAP-PFM-QRY-015-13
    preconditions: A report has both enabled and manually paused schedules plus a retained completed file.
    steps: 'Delete the report, inspect both schedules and try resuming or running them.'
    expected: >-
      Both carry the report-deleted pause, retain their history and refuse new runs; the completed file
      remains.
    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/e2e/query-schedules.e2e.spec.js#pauses the schedule
        report_deleted, its report gone
      - 'services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#refuses to resume it (400)'
  - id: ATS-PFM-QRY-015-19
    title: A report schedule renders the current presentation
    category: interaction
    level: api
    exercises:
      - CAP-PFM-QRY-013
      - CAP-PFM-QRY-015
    proves:
      - BR-CAP-PFM-QRY-013-04
      - BR-CAP-PFM-QRY-015-12
    preconditions: A table report has a PDF schedule and its layout changes after scheduling.
    steps: 'Run the schedule, inspect its export and remove the owner’s report-use grant before the next occurrence.'
    expected: >-
      The first occurrence uses the updated presentation; the next fails without a new file or delivery and
      pauses the schedule.
    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/rendering/render-report.integration.spec.js#fails
        a requester who may not use reports access_lost, saying so plainly
      - >-
        services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js#refuses Excel for a dashboard
        (400 at options.format)
  - id: ATS-PFM-QRY-015-20
    title: Retry reuses each recipient’s file delivery
    category: interaction
    level: api
    exercises:
      - CAP-PFM-QRY-014
      - CAP-PFM-QRY-015
    proves:
      - BR-CAP-PFM-QRY-014-09
      - BR-CAP-PFM-QRY-015-08
    preconditions: A query schedule has two active recipients and a completed export.
    steps: 'Process the occurrence, retry it and follow one recipient link after that recipient loses membership.'
    expected: >-
      Two recipient-keyed communications requests remain; the departed recipient receives the invalid-link
      page.
    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/integration/services/exports/query-export-routes.integration.spec.js#answers
        the plain page for a recipient no longer on the schedule
      - >-
        services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js#submits
        nothing new when the same run is run again
evidence:
  - >-
    Pinned reference:
    react-console:acceptance/reporting/playwright/journeys/print-and-export/RPT-ACC-0358.spec.ts
  - 'Pinned reference: react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0424.spec.ts'
  - 'Pinned reference: react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0425.spec.ts'
  - 'Pinned reference: react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0427.spec.ts'
  - 'Pinned reference: react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0428.spec.ts'
  - 'Pinned reference: react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0432.spec.ts'
  - 'Pinned reference: react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0436.spec.ts'
  - 'Pinned reference: react-console:acceptance/reporting/playwright/journeys/schedules/RPT-ACC-0437.spec.ts'
  - 'Pinned reference: services-platform:modules/queries/tests/e2e/query-schedules.e2e.spec.js'
  - >-
    Pinned reference:
    services-platform:modules/queries/tests/integration/services/schedules/query-schedule-routes.integration.spec.js
  - >-
    Pinned reference:
    services-platform:modules/queries/tests/integration/services/schedules/scheduled-delivery.integration.spec.js
coverage:
  rule: covered
  transition: 'gap: FND-PFM-QRY-065'
  validation: covered
  permission: covered
  edge: covered
  failure: covered
  boundary: covered
  concurrency: covered
  invariant: 'gap: FND-PFM-QRY-065'
  interaction: covered
coverage_findings:
  - FND-PFM-QRY-065
transition_obligations:
  - state: STATE-PFM-QRY-007
    transition: 1
    from: enabled
    to: paused
    trigger: An authorized person pauses recurrence.
    source: 'services-platform:modules/queries/services/schedules/query-schedule-library.ts'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-007
    transition: 2
    from: paused
    to: enabled
    trigger: An authorized person resumes a user-paused schedule.
    source: 'services-platform:modules/queries/aws/api/query-schedules.routes.ts:resumeQuerySchedule'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-007
    transition: 3
    from: paused by Platform
    to: enabled
    trigger: The person resumes after an automatic pause.
    source: 'services-platform:modules/queries/services/schedules/query-schedule-library.ts'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-007
    transition: 4
    from: imported and paused
    to: enabled
    trigger: The imported schedule is resumed.
    source: 'services-platform:docs/migrations/query-scheduling-exports/README.md#D13'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-007
    transition: 5
    from: enabled
    to: paused by Platform
    trigger: Automatic execution detects source access loss.
    source: 'services-platform:modules/queries/services/schedules/scheduled-delivery.ts'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-007
    transition: 6
    from: enabled
    to: paused by Platform
    trigger: The failure streak reaches five runs.
    source: >-
      services-platform:node_modules/@rhythmsoftware/macroservice-schedules/dist/schedule-repository.js
      (DEFAULT_AUTO_PAUSE_AFTER_FAILURES)
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-007
    transition: 7
    from: enabled
    to: paused for a deleted report
    trigger: The source report is removed.
    source: 'services-platform:modules/queries/services/reports/report-library.ts:removeReport'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-007
    transition: 8
    from: paused
    to: paused for a deleted report
    trigger: The paused schedule’s source report is removed.
    source: 'services-platform:modules/queries/services/reports/report-library.ts:removeReport'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-007
    transition: 9
    from: paused for a deleted report
    to: deleted
    trigger: The remaining report-deleted schedule is removed.
    source: 'services-platform:modules/queries/db/query-schedules.table.ts'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-007
    transition: 10
    from: enabled
    to: deleted
    trigger: The enabled schedule is removed.
    source: 'services-platform:modules/queries/aws/api/query-schedules.routes.ts:deleteQuerySchedule'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-007
    transition: 11
    from: paused
    to: deleted
    trigger: The paused schedule is removed.
    source: 'services-platform:modules/queries/aws/api/query-schedules.routes.ts:deleteQuerySchedule'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-008
    transition: 1
    from: queued
    to: running
    trigger: The delivery consumer begins the occurrence.
    source: 'services-platform:modules/queries/aws/logic/query-schedules.lambda.ts'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-008
    transition: 2
    from: running
    to: succeeded
    trigger: File production and recipient outcome recording finish.
    source: 'services-platform:modules/queries/services/schedules/scheduled-delivery.ts'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-008
    transition: 3
    from: running
    to: skipped
    trigger: The file has no records and empty-result suppression is enabled.
    source: 'services-platform:modules/queries/services/schedules/scheduled-delivery.ts'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-008
    transition: 4
    from: running
    to: failed
    trigger: A request refusal or exhausted infrastructure attempt settles the run.
    source: 'services-platform:modules/queries/services/schedules/scheduled-report-delivery.ts'
    gap: FND-PFM-QRY-065
  - state: STATE-PFM-QRY-008
    transition: 5
    from: running
    to: running
    trigger: An infrastructure failure returns unfinished work to the queue.
    source: 'services-platform:docs/migrations/query-scheduling-exports/README.md#D12'
    gap: FND-PFM-QRY-065
unproved_rules: []
---

# Deliver recurring query and report files: Capability Test Specification

## Coverage

| Rule | Scenario or Finding |
|---|---|
| `BR-CAP-PFM-QRY-015-01` | `ATS-PFM-QRY-015-01` |
| `BR-CAP-PFM-QRY-015-02` | `ATS-PFM-QRY-015-02` |
| `BR-CAP-PFM-QRY-015-03` | `ATS-PFM-QRY-015-03`, `ATS-PFM-QRY-015-17` |
| `BR-CAP-PFM-QRY-015-04` | `ATS-PFM-QRY-015-04` |
| `BR-CAP-PFM-QRY-015-05` | `ATS-PFM-QRY-015-05` |
| `BR-CAP-PFM-QRY-015-06` | `ATS-PFM-QRY-015-06` |
| `BR-CAP-PFM-QRY-015-07` | `ATS-PFM-QRY-015-07` |
| `BR-CAP-PFM-QRY-015-08` | `ATS-PFM-QRY-015-08`, `ATS-PFM-QRY-015-20` |
| `BR-CAP-PFM-QRY-015-09` | `ATS-PFM-QRY-015-09` |
| `BR-CAP-PFM-QRY-015-10` | `ATS-PFM-QRY-015-10` |
| `BR-CAP-PFM-QRY-015-11` | `ATS-PFM-QRY-015-11` |
| `BR-CAP-PFM-QRY-015-12` | `ATS-PFM-QRY-015-12`, `ATS-PFM-QRY-015-19` |
| `BR-CAP-PFM-QRY-015-13` | `ATS-PFM-QRY-015-13`, `ATS-PFM-QRY-015-18` |
| `BR-CAP-PFM-QRY-015-14` | `ATS-PFM-QRY-015-14` |
| `BR-CAP-PFM-QRY-015-15` | `ATS-PFM-QRY-015-15` |

## 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-015-03` |
| Journey dependency | `ATS-PFM-QRY-015-16` |
| `CAP-PFM-QRY-006` | `ATS-PFM-QRY-015-17` |
| `CAP-PFM-QRY-011` | `ATS-PFM-QRY-015-18` |
| `CAP-PFM-QRY-013` | `ATS-PFM-QRY-015-19` |
| `CAP-PFM-QRY-014` | `ATS-PFM-QRY-015-20` |

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