---
id: CAP-PFM-QRY-002
title: Answer a question within the reader’s access
feature: FEAT-PFM-QRY-01
product_area: platform
module: queries
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
supersedes:
  - CAP-RPT-QRY-005
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-platform:docs/queries/semantic-query-layer.md#Decisions Recorded (Andrew, 2026-10-08) 8'
  - 'services-platform:docs/queries/semantic-query-layer.md#Decisions Recorded (Andrew, 2026-10-08) 9'
  - 'services-platform:docs/queries/semantic-query-layer.md#Decisions Recorded (Andrew, 2026-10-08) 13'
  - 'services-platform:docs/queries/semantic-query-layer.md#Decisions Recorded (Andrew, 2026-10-08) 15'
  - >-
    services-platform:docs/queries/semantic-query-layer.md#A value asked for when a saved query runs
    (`$parameter`, 2026-10-13)
purpose: >-
  Let staff investigate workspace data through filters, ordering and grouped results evaluated with their own
  access and calendar.
outcomes:
  - Staff investigate data without writing database statements.
  - Workspace and dataset access constrain results.
  - Paging follows the question’s declared ordering.
concepts:
  - CON-PFM-QRY-001
  - CON-PFM-QRY-002
actors:
  - ACT-PFM-013
  - ACT-PFM-014
surfaces:
  - console
  - api
preconditions: []
postconditions: []
permissions:
  - key: platform.queries.read
    where_checked: api
    scope: tenant
  - key: <application>.<dataset>.query (the owner's key)
    where_checked: service
    scope: tenant
rules:
  - id: BR-CAP-PFM-QRY-002-01
    proved_by: [ATS-PFM-QRY-001-12, ATS-PFM-QRY-002-01, ATS-PFM-QRY-002-17, ATS-PFM-QRY-002-19, ATS-PFM-QRY-003-12, ATS-PFM-QRY-004-08, ATS-PFM-QRY-014-11, TST-PFM-QRY-296]
    statement: >-
      Query execution confines source records and joins to the requested workspace, with database row security
      also preventing cross-workspace reads when a compiled predicate is absent.
    kind: invariant
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/run-query.integration.spec.js#confines
      a statement carrying no tenant predicate at all, so row-level security holds beneath the compiler
    origin: 'services-platform:docs/queries/semantic-query-layer.md#Decisions Recorded (Andrew, 2026-10-08) 9'
  - id: BR-CAP-PFM-QRY-002-02
    proved_by: [ATS-PFM-QRY-002-02, TST-PFM-QRY-289]
    statement: >-
      Queries use a read-only reader transaction with a time limit; timeouts produce an actionable limit
      message, and other failures reveal neither statement text nor stored data.
    kind: invariant
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/read-only-execution.integration.spec.js#refuses
      a write, whatever the statement carries, because the transaction is read-only
    origin: none
  - id: BR-CAP-PFM-QRY-002-03
    proved_by: [ATS-PFM-QRY-002-03, TST-PFM-QRY-296]
    statement: >-
      Unsupported fields, operators and relationships are rejected without distinguishing inaccessible
      metadata from metadata that does not exist.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/run-query.integration.spec.js#refuses
      a column no owner registered exactly as it refuses one that does not exist at all
    origin: none
  - id: BR-CAP-PFM-QRY-002-04
    proved_by: [ATS-PFM-QRY-002-04, TST-PFM-QRY-296]
    statement: >-
      Criterion validation rejects blank text, empty identity lists, fractional integer values, unsafe whole
      numbers and dates outside the required calendar-date form.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/run-query.integration.spec.js#refuses
      a blank text value, which would match every contact rather than narrow anything
    origin: none
  - id: BR-CAP-PFM-QRY-002-05
    proved_by: [ATS-PFM-QRY-002-05, TST-PFM-QRY-296]
    statement: >-
      Paging cursors carry the query’s ordered position, and malformed cursors, cursors from another query or
      cursors with incompatible keys are rejected.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/run-query.integration.spec.js#refuses
      a cursor issued for a different query, rather than paging the wrong rows
    origin: none
  - id: BR-CAP-PFM-QRY-002-06
    proved_by: [ATS-PFM-QRY-002-06, TST-PFM-QRY-287]
    statement: >-
      Requested totals count all matching base records or groups in the page’s database snapshot,
      independently of cursor position and join multiplication; unrequested totals are omitted.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/query-totals.integration.spec.js#counts
      the base records, not the rows the joins produced
    origin: none
  - id: BR-CAP-PFM-QRY-002-07
    proved_by: [ATS-PFM-QRY-002-07, TST-PFM-QRY-290]
    statement: >-
      Recently Viewed returns this person’s workspace records once each at their latest viewing time, newest
      first, and rejects system executions without a person.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/recently-viewed-scope.integration.spec.js#answers
      each caller the records that caller viewed, and no other caller’s
    origin: 'services-platform:docs/queries/semantic-query-layer.md#Decisions Recorded (Andrew, 2026-10-08) 15'
  - id: BR-CAP-PFM-QRY-002-08
    proved_by: [ATS-PFM-QRY-002-08, TST-PFM-QRY-270]
    statement: >-
      The current-person criterion resolves from the execution identity on a user-bearing field with a
      compatible operator, and rejects unsuitable fields, operators and non-person executions.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/current-user-criterion.integration.spec.js#answers
      a second caller their own tasks, from the very same criterion
    origin: none
  - id: BR-CAP-PFM-QRY-002-09
    proved_by: [ATS-PFM-QRY-002-09, TST-PFM-QRY-234]
    statement: >-
      Unsaved execution rejects requested-at-run values and supplied parameter maps, while validation reports
      those uses as located problems in a successful validation response.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/e2e/saved-queries.e2e.spec.js#refuses a token sent to the
      validate route, which judges a request on its own
    origin: >-
      services-platform:docs/queries/semantic-query-layer.md#A value asked for when a saved query runs
      (`$parameter`, 2026-10-13) (Andrew, 2026-10-13)
  - id: BR-CAP-PFM-QRY-002-10
    proved_by: [ATS-PFM-QRY-002-10, ATS-PFM-QRY-020-07, TST-PFM-QRY-226, TST-PFM-QRY-296]
    statement: >-
      Calendar and relative-date criteria use the workspace’s time zone and calendar, and date previews report
      the calendar used.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/run-query.integration.spec.js#reads
      a day as that day in the tenant's zone, not in UTC
    origin: none
  - id: BR-CAP-PFM-QRY-002-11
    proved_by: [ATS-PFM-QRY-002-11, ATS-PFM-QRY-002-18, TST-PFM-QRY-234]
    statement: >-
      Validation collects located query problems without executing the query, while execution stops at its
      first invalid part.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/e2e/saved-queries.e2e.spec.js#answers 200 and the problems for a
      query it will not run, rather than a refusal
    origin: none
  - id: BR-CAP-PFM-QRY-002-12
    proved_by: [ATS-PFM-QRY-002-12, TST-PFM-QRY-225]
    statement: >-
      Linked result cells identify records whose identities the reader may select, and an override referring
      to a record absent from the result is rejected.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/e2e/datasets.e2e.spec.js#refuses a link override naming a record
      the result does not have as 400 QueryLinkInvalid
    origin: none
  - id: BR-CAP-PFM-QRY-002-13
    proved_by: [ATS-PFM-QRY-002-13, TST-PFM-QRY-293]
    statement: >-
      Reference columns display the referenced record’s name, fall back to its identity when nameless, and
      remain empty when absent; an explicitly selected identity stays separate.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/reference-display-values.integration.spec.js#shows
      each spouse’s name, the id as text where the spouse has no name, and null where there is no spouse
    origin: none
  - id: BR-CAP-PFM-QRY-002-14
    proved_by: [ATS-PFM-QRY-002-14, TST-PFM-QRY-296]
    statement: >-
      A field reached through a record reference supports one many-to-one traversal and rejects a second
      traversal.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/run-query.integration.spec.js#refuses
      a second hop through the referenced record's own reference
    origin: 'services-platform:docs/queries/semantic-query-layer.md#Decisions Recorded (Andrew, 2026-10-08) 13'
  - id: BR-CAP-PFM-QRY-002-15
    proved_by: [ATS-PFM-QRY-002-15]
    statement: >-
      The documented query bounds are 255 selected fields, five sort keys, 100 criteria at depth six, two
      to-one hops and pages of at most one thousand rows, defaulting to one hundred.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: documented
    source: 'services-platform:docs/queries/semantic-query-layer.md#10.6 Complexity limits (first release)'
    origin: none
    note: >-
      The external request schema is outside the pinned source examined here; the cited design establishes
      documented limits only.
  - id: BR-CAP-PFM-QRY-002-16
    proved_by: [ATS-PFM-QRY-002-16, TST-PFM-QRY-286]
    statement: >-
      Grouped calculations apply sums, averages, minima and maxima to the matching group rows, preserve
      appropriate result types, and yield no value for a field absent from every row.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/query-aggregates.integration.spec.js#answers
      one group for the three contacts, every aggregate computed over exactly those rows
    origin: none
scenarios:
  - id: SC-CAP-PFM-QRY-002-01
    given: Two workspaces use identical contact and employer identities.
    when: A person queries contacts with an employer value in the first workspace.
    then: The answer includes only records and related values from that workspace.
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/run-query.integration.spec.js#answers
      no row, pick or joined value belonging to another tenant, though the ids are the same
  - id: SC-CAP-PFM-QRY-002-02
    given: A task question uses the current-person criterion.
    when: Two people execute that same question.
    then: Each result contains the tasks assigned to its own runner.
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/current-user-criterion.integration.spec.js#answers
      a second caller their own tasks, from the very same criterion
  - id: SC-CAP-PFM-QRY-002-03
    given: The workspace calendar uses a time zone different from UTC.
    when: A datetime criterion asks for records on a calendar day.
    then: Matching follows the full workspace day.
    provenance: test
    source: >-
      services-platform:modules/queries/tests/integration/services/execute/run-query.integration.spec.js#reads
      a day as that day in the tenant's zone, not in UTC
edge_cases: []
constraints: []
depends_on:
  - CAP-PFM-QRY-001
related:
  - CAP-PFM-QRY-001
  - CAP-PFM-QRY-006
  - CAP-PFM-QRY-014
journeys:
  - JNY-PFM-QRY-002
open_questions: []
operations:
  - runDatasetQuery
  - validateDatasetQuery
  - resolveDateExpressions
tables: []
evidence:
  - 'Pinned reference: services-platform:docs/queries/semantic-query-layer.md'
  - 'Pinned reference: services-platform:modules/queries/tests/e2e/datasets.e2e.spec.js'
  - 'Pinned reference: services-platform:modules/queries/tests/e2e/saved-queries.e2e.spec.js'
  - >-
    Pinned reference:
    services-platform:modules/queries/tests/integration/services/execute/current-user-criterion.integration.spec.js
  - >-
    Pinned reference:
    services-platform:modules/queries/tests/integration/services/execute/query-aggregates.integration.spec.js
  - >-
    Pinned reference:
    services-platform:modules/queries/tests/integration/services/execute/query-totals.integration.spec.js
  - >-
    Pinned reference:
    services-platform:modules/queries/tests/integration/services/execute/read-only-execution.integration.spec.js
  - >-
    Pinned reference:
    services-platform:modules/queries/tests/integration/services/execute/recently-viewed-scope.integration.spec.js
  - >-
    Pinned reference:
    services-platform:modules/queries/tests/integration/services/execute/reference-display-values.integration.spec.js
  - >-
    Pinned reference:
    services-platform:modules/queries/tests/integration/services/execute/run-query.integration.spec.js
controls: [TC-AVL-001, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-CRY-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-003, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-VEN-001, TC-VEN-002, TC-VEN-003]
exercised_by: [FAS-PFM-QRY-01-01, FAS-PFM-QRY-01-02, FAS-PFM-QRY-01-03, FAS-PFM-QRY-01-04, FAS-PFM-QRY-01-05]
suites: [TST-PFM-QRY-225, TST-PFM-QRY-226, TST-PFM-QRY-234, TST-PFM-QRY-270, TST-PFM-QRY-286, TST-PFM-QRY-287, TST-PFM-QRY-289, TST-PFM-QRY-290, TST-PFM-QRY-293, TST-PFM-QRY-296]
---

# Answer a question within the reader’s access

## Purpose

Let staff investigate workspace data through filters, ordering and grouped results evaluated with their own access and calendar.

## How It Works

A staff member chooses a dataset and builds a question in the designer. They select fields, add criteria and choose ordering or grouping. Validation gives them located problems to repair before they run the question. Execution checks the resolved dataset model and reads through the protected database reader. Results supply values and record-opening information for the screen. The person can continue through later pages or ask for a matching total. Relative dates use the customer workspace’s calendar. A current-person condition lets colleagues reuse the same question for their own work. Unsupported input, lost access and execution limits produce refusals or failure messages.

## Relationships

Execution uses resolved dataset descriptions. Saved questions, navigation and file production reuse its result semantics.
