flightpack/reporting: reports as data, not code
A dataset catalogue, a query compiler that only accepts names from an allowlist, and result frames that a grid, a pivot and a chart can all draw. Two commits old, with the gaps listed.
flightpack/reporting is the youngest serious package: two commits on 12 October 2026, a version tag, and a README with a section called "Not built yet" that is longer than most packages' feature lists. I like it for that reason. It also holds one idea I would copy into any product with reports: a report is data, not code.
The idea
A developer who wants a new report should not write a new query. They declare a dataset: which table or view it reads, which columns are dimensions (things you group by), which are measures (things you count or sum), a label in English and Malay for each, a permission, and the column that carries row scope. After that, any report over that dataset is a request that names keys from the declaration.
Dataset (declared once) table, dimensions, measures, scope column, permission Request (from the screen) dataset key + dimension keys + measure keys + filters QueryCompiler keys -> GROUP BY SQL, PostgreSQL only ResultFrame columns + rows + totals -> grid | pivot | chart
The compiler turns the request into a grouped query, and nothing the caller sends reaches the SQL as an identifier. Only names from the dataset's own declaration can become a column or an aggregate. That is the sentence in the README, and it is the design rule I would check first in a review.
Who may see which rows
The package does not guess row scope. The host application binds a resolver that says which rows the current user may read, and the engine applies it to every query. The default resolver allows every row. The README says outright that this is right for the demo data and wrong for anything scoped. I would rather a package say that in the install notes than have the first deployment find out.
What the screen is made of
| Component | Job |
|---|---|
DataGrid | Rows with honest totals |
PivotTable | Rows by columns, with per-column shading |
ChartPanel | The same frame as a chart |
ReportExplorer | Choose dataset, dimensions and measures; save the view |
Saved views belong to their owner. The API is small: list the datasets the user may read, run a query, list sample reports, and create, list and delete views. Two permissions guard it, one to view and one to manage.
What is not built
The README lists it plainly: rollup tables and refresh jobs, scheduled delivery, spreadsheet and PDF renderers on frames, drill paths, a test suite inside the package (the host's tests cover it for now) and an alternative grid. A package that says what it lacks is easier to adopt than one that hides it, and it is the same habit as "Done in code" on our board, described in the product deck tour.
How it installs
The install command can seed demo data. Frontend wiring is manual: the routes snippet, a menu entry and the locale files are added by hand, as with the older packages, and not through the module registry described in the modular design post. Moving it onto the registry is a fair candidate for the next change.
What I would tell another small team
If a product will have more than a handful of reports, spend a day on the dataset declaration before the first report. Every later report becomes a request, row scope is written in one place, and nobody can paste a column name into a query that should not see it.