---
id: DOM-PFM-QRY-003
title: Report
realises: CON-PFM-QRY-003
product_area: platform
module: queries
revision: 1
status: draft
design_intent: confirmed
implementation_evidence: observed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
owned_by: SVC-PFM-QRY-queries
readable_by: []
custom_fields: none
identity: >-
  Stored reports have workspace-scoped system identities and case-insensitive names unique to their
  owner. Built-in presentations ship as console components; a stored coded report refers to the
  component it opens.
attributes:
  - name: name and description
    kind: text
    required: true
    computed: false
    notes: The name accepts one to 120 characters; an optional description accepts up to one thousand.
  - name: kind
    kind: enum
    required: true
    computed: false
    notes: >-
      The stored kind is designed, coded, table or dashboard. Excel rendering is available for coded
      and table reports.
  - name: component
    kind: text
    required: false
    computed: false
    notes: A coded report requires its console component; other kinds cannot specify one.
  - name: definition
    kind: collection
    required: true
    computed: false
    notes: >-
      The service stores the layout unchanged within 512 KiB and inspects dashboard source
      references rather than interpreting presentation details.
  - name: saved query source
    kind: reference
    required: false
    computed: false
    notes: A non-dashboard report names one saved query directly; dashboards use their source collection.
  - name: sources
    kind: collection
    required: true
    computed: true
    notes: >-
      Source rows retain saved-query versions for change detection. Dashboards retain up to fifty
      distinct sources in first-widget order.
  - name: owner
    kind: reference
    required: true
    computed: false
    notes: The person creating a report or copy becomes its owner.
  - name: audience
    kind: enum
    required: true
    computed: false
    notes: >-
      Sharing can be private, role-based or workspace-wide and is constrained by every source
      audience.
  - name: source changed
    kind: computed
    required: false
    computed: true
    notes: >-
      Change detection compares source definitions with the saved versions; a source rename alone
      does not count.
  - name: version and lock
    kind: computed
    required: true
    computed: true
    notes: >-
      Save and delete requests carry the version read. A record lock separately prevents
      replacement.
relationships:
  - to: DOM-PFM-QRY-002
    cardinality: many-to-many
    ownership: >-
      The report maintains its source references; each source constrains audience width and
      saved-query deletion.
    cross_service: false
  - to: DOM-PFM-QRY-004
    cardinality: one-to-many
    ownership: >-
      File and schedule rows refer to reports. Deletion clears an export reference while retaining
      its completed file and pauses dependent schedules.
    cross_service: false
invariants:
  - id: INV-DOM-PFM-QRY-003-01
    statement: >-
      Report discovery includes owners, selected-role holders, workspace audiences and report
      managers; others receive not found.
    enforced_at:
      - service
    provenance: observed
    source: 'services-platform:modules/queries/services/reports/report-access.ts'
  - id: INV-DOM-PFM-QRY-003-02
    statement: >-
      Writing a report checks its audience against locked sources in the same transaction, including
      every dashboard source.
    enforced_at:
      - service
      - database
    provenance: observed
    source: 'services-platform:modules/queries/services/persistence/reports.ts:requireNoWiderThanQuery'
  - id: INV-DOM-PFM-QRY-003-03
    statement: >-
      Dashboards omit the direct saved-query field and allow at most fifty distinct sources; other
      report kinds require one direct source.
    enforced_at:
      - service
      - database
    provenance: observed
    source: >-
      services-platform:modules/queries/db/reports.table.ts (reports_saved_query_check);
      modules/queries/db/dashboard-sources.ts
  - id: INV-DOM-PFM-QRY-003-04
    statement: A report name is case-insensitively unique per owner and workspace.
    enforced_at:
      - service
      - database
    provenance: observed
    source: >-
      services-platform:modules/queries/services/persistence/reports.ts
      (reports_tenant_owner_name_uidx)
  - id: INV-DOM-PFM-QRY-003-05
    statement: A report write replaces its complete source-reference collection within the same transaction.
    enforced_at:
      - service
    provenance: observed
    source: 'services-platform:modules/queries/services/persistence/reports.ts'
  - id: INV-DOM-PFM-QRY-003-06
    statement: >-
      Report deletion pauses dependent schedules atomically without deleting source queries or
      completed files.
    enforced_at:
      - service
      - database
    provenance: observed
    source: 'services-platform:modules/queries/services/reports/report-library.ts:removeReport'
  - id: INV-DOM-PFM-QRY-003-07
    statement: >-
      Presentation access grants no source-data authority; inaccessible sources reveal only their
      identity and change indication.
    enforced_at:
      - service
    provenance: observed
    source: 'services-platform:modules/queries/services/reports/report-library.ts'
  - id: INV-DOM-PFM-QRY-003-08
    statement: >-
      Report saves provide the read version in their body and deletes in their parameter; absent
      versions are refused and stale versions conflict.
    enforced_at:
      - api
      - service
    provenance: documented
    source: 'services-platform:docs/milestones/plans/RPT-M1-plan.md#RPT-M1'
physical:
  - platform.reports
  - platform.report_sources
  - platform.report_shared_roles
evidence:
  - >-
    services-platform at ad3f6a6: modules/queries/db/reports.table.ts, report-sources.table.ts,
    report-shared-roles.table.ts, dashboard-sources.ts; services/reports/*.ts;
    services/persistence/reports.ts; docs/queries/reports.md; docs/milestones/plans/RPT-M1-plan.md
    (D1–D10, approved 2026-10-21)
  - 'react-console at baf6dae: lib/reporting/catalog/*.ts; lib/dashboard-lab/catalog.ts'
---

# Report

## What It Models

A report adds a presentation to saved questions. A dashboard combines multiple questions while retaining the sources needed for access checks and change indicators.

## Identity and Attributes

Ownership, audience and source versions belong to the stored report. Built-in components remain console code until someone saves a coded copy.

## Relationships

Source references protect saved queries from deletion and provide the boundary for sharing. Export files and schedules retain their own execution histories.

## Invariants

The invariant rows define audience checks, source replacement and version-aware writes. Catalog visibility alone does not guarantee an executable joined query.

## How It Is Stored and Shared

The query service stores report definitions and source rows; console components interpret the layout. Rendering is a separate background workflow.

## Open Design Questions

Report approval and runtime coverage remain limited by the recorded reporting and catalog findings.
