- Shipped
- September 2, 2026 at 3:45 AM UTC
- Author
- Kamo
- Commit
- 2ba1270
The service half of the framework: the catalogue, the run, the pickers, four exporters, saved views and schedules. Authorization is explicit on every path, because this service runs permitAll at the filter chain. Two rights are always in play — VIEW_REPORTS opens the module, and the report's own domain right decides whether that report may be run and how much of the organization it covers. VIEW_REPORTS alone admits nobody to any data, which is what makes the app safe to switch on for a tenant. ReportScopeResolver reads the platform's existing OWN/ALL sibling rights and nothing invented for reporting. A report naming no narrower right is organization-wide and says so in a note the studio and every export print verbatim — a total produced under "your own records only" is not the same document as one produced over the whole organization, and a reader cannot tell them apart otherwise. sanitise() is the boundary that keeps a saved view from becoming a user-defined report: a request can only choose among what the definition already declared. It strips unknown columns, grouping levels and parameters, but deliberately leaves an unknown column in a FILTER for the query engine to refuse — dropping a hidden column changes the presentation, dropping a filter changes the answer. Exports read the same ReportResult the screen was drawn from and format through the same ReportFormat descriptor, so a figure in a PDF and the cell it came from cannot disagree. The workbook writes numbers as numbers with a format mask rather than as pre-formatted strings, which is the difference between a spreadsheet and a CSV with a different extension. The PDF carries the organization, the period, the data scope, who ran it and page numbers. A scheduled report runs as its OWNER, with rights recomputed at run time, so revoking access stops a schedule at its next run rather than whenever a session expires. nextRunAt advances before delivery: there is no ShedLock in this fleet and replicas: 1 is all that prevents a double send. pdfbox and poi-ooxml are added HERE and not to kamo-shared-library, which every service component-scans — they would otherwise ship into ~60 images that never render a report. kamo.reporting.enabled is set in this service's ConfigMap and nowhere else; that property is what stops a report bean being constructed in services that cannot satisfy it. Also renames a stale entry in **************** ec2ae5e renamed **************** to #syncLabels without renaming its baseline line, which failed the ratchet on origin/main in both directions at once. The handler does resolve a caller — getOrganizationFromRequest, 401 when null — so this is a rename, not a widening.