ReviewOS

also looking at this

stacks/reportshq

Expand BunPress guide and pre-E2E quality gates

#35
Merged glennmichael123 wants to merge docs/bunpress-product-guide into main
40 files +1524 -373
docs/concepts.mdadded+44-0
Changes to docs/concepts.md
@@ -0,0 +1,44 @@
1# Reporting concepts
2
3ReportsHQ is an in-process reporting engine. It reads only the models, measures, time fields, dimensions and relations the application declares, compiles a bounded query, and returns one stable block shape to the included chart components or JSON API.
4
5## Registry
6
7The registry is the allowlist. A model description names the table and the fields that reporting may use. A database column that is not declared is not available to the builder or query compiler.
8
9## Measure
10
11A measure is a value to aggregate, such as revenue, orders or users. It defines the aggregate operation, optional source column and unit.
12
13```ts
14measures: {
15 revenue: { aggregate: 'sum', column: 'total_amount', unit: 'currency' },
16 orders: { aggregate: 'count' },
17}
18```
19
20## Dimension
21
22A dimension groups a measure, such as status, country or plan. The current TypeScript compiler can limit a dimensioned result to at most 500 rows. It does not synthesize an `Other` bucket for omitted values, so a limited chart is not a complete total.
23
24## Time grain
25
26A time field can be bucketed by a supported grain such as day, week or month. Buckets are calculated in the report timezone, not by applying a fixed offset. This matters across daylight-saving changes and at both edges of a date range.
27
28## Relation and fan-out
29
30A relation explains how two declared models join. Mark a relation `fansOut` when one source row can match several target rows. ReportsHQ refuses measures that would be multiplied by that join.
31
32For example, summing an order total while grouping through its line items counts the same order once per item. The compiler refuses that query. Declare line revenue on the line-item model instead.
33
34## Block
35
36A block is one report tile. Its kind controls presentation, while its query selects a model, measure, time field, dimension and filters. All block kinds receive the same result contract: series, totals and an optional error.
37
38## Draft and published report
39
40In the current Laravel source, the builder edits a draft and publishing creates the revision shown by ordinary views and share links. In a Stacks host, draft storage and publishing depend on its `ReportStore`; this site's code-defined report has no browser editor or share link.
41
42## Refusal
43
44When a query cannot produce a defensible number, the block returns an explanation instead of a plausible guess. The rest of the report can still render. A refusal is part of the data contract, not a transport failure.