@happyvertical/smrt-reports 0.57.6 → 0.57.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +10 -0
- package/dist/chunks/runtime-time-D7JZ1e4J.js +1052 -0
- package/dist/chunks/runtime-time-D7JZ1e4J.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -591
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +28 -4
- package/dist/playground.js +1 -1
- package/dist/playground.js.map +1 -1
- package/dist/recipes.d.ts +21 -0
- package/dist/recipes.d.ts.map +1 -1
- package/dist/runtime-compiler.d.ts +7 -40
- package/dist/runtime-compiler.d.ts.map +1 -1
- package/dist/runtime-dimensions.d.ts +43 -0
- package/dist/runtime-dimensions.d.ts.map +1 -0
- package/dist/runtime-memory.d.ts +81 -0
- package/dist/runtime-memory.d.ts.map +1 -0
- package/dist/runtime-plan.d.ts +121 -0
- package/dist/runtime-plan.d.ts.map +1 -0
- package/dist/runtime-report.d.ts.map +1 -1
- package/dist/runtime-server.d.ts.map +1 -1
- package/dist/runtime-spec-hash.d.ts +11 -0
- package/dist/runtime-spec-hash.d.ts.map +1 -0
- package/dist/runtime-spec.d.ts +16 -4
- package/dist/runtime-spec.d.ts.map +1 -1
- package/dist/runtime-time.d.ts +41 -0
- package/dist/runtime-time.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +37 -12
- package/dist/spec.d.ts +25 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +2 -0
- package/dist/state.js +1 -1
- package/dist/state.js.map +1 -1
- package/dist/svelte/ReportConfirmation.svelte +97 -24
- package/dist/svelte/ReportConfirmation.svelte.d.ts +20 -0
- package/dist/svelte/ReportConfirmation.svelte.d.ts.map +1 -1
- package/dist/svelte/ReportDetail.svelte +263 -12
- package/dist/svelte/ReportDetail.svelte.d.ts +10 -1
- package/dist/svelte/ReportDetail.svelte.d.ts.map +1 -1
- package/dist/svelte/ReportPicker.svelte +47 -14
- package/dist/svelte/ReportPicker.svelte.d.ts +3 -0
- package/dist/svelte/ReportPicker.svelte.d.ts.map +1 -1
- package/dist/svelte/ReportResult.svelte +216 -35
- package/dist/svelte/ReportResult.svelte.d.ts +8 -2
- package/dist/svelte/ReportResult.svelte.d.ts.map +1 -1
- package/dist/svelte/RuntimeReportWidgetOptions.svelte +9 -1
- package/dist/svelte/RuntimeReportWidgetOptions.svelte.d.ts.map +1 -1
- package/dist/svelte/SavedReportCard.svelte +242 -0
- package/dist/svelte/SavedReportCard.svelte.d.ts +30 -0
- package/dist/svelte/SavedReportCard.svelte.d.ts.map +1 -0
- package/dist/svelte/SavedReports.svelte +206 -33
- package/dist/svelte/SavedReports.svelte.d.ts +13 -0
- package/dist/svelte/SavedReports.svelte.d.ts.map +1 -1
- package/dist/svelte/SavedReportsWidget.svelte +59 -0
- package/dist/svelte/SavedReportsWidget.svelte.d.ts +19 -0
- package/dist/svelte/SavedReportsWidget.svelte.d.ts.map +1 -0
- package/dist/svelte/client.d.ts.map +1 -1
- package/dist/svelte/client.js +3 -0
- package/dist/svelte/describe.d.ts +94 -0
- package/dist/svelte/describe.d.ts.map +1 -0
- package/dist/svelte/describe.js +249 -0
- package/dist/svelte/index.d.ts +4 -1
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +4 -1
- package/dist/svelte/messages.d.ts +48 -0
- package/dist/svelte/messages.d.ts.map +1 -1
- package/dist/svelte/messages.js +59 -11
- package/dist/svelte/playground.d.ts +2 -2
- package/dist/svelte/playground.d.ts.map +1 -1
- package/dist/svelte/playground.js +1 -1
- package/dist/svelte/types.d.ts +2 -0
- package/dist/svelte/types.d.ts.map +1 -1
- package/package.json +13 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-time.d.ts","sourceRoot":"","sources":["../src/runtime-time.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,2EAA2E;AAC3E,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,6EAA6E;IAC7E,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,sEAAsE;IACtE,KAAK,CAAC,EAAE,sBAAsB,CAAC;IAC/B,uEAAuE;IACvE,YAAY,EAAE,OAAO,CAAC;CACvB;AAmDD,mEAAmE;AACnE,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,GAAG,IAAI,GAClB,mBAAmB,CAMrB;AAUD;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,IAAI,GACR,sBAAsB,GAAG,IAAI,CA2H/B;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,IAAI,GACR,uBAAuB,CAkBzB"}
|
package/dist/smrt-knowledge.json
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
"sensitiveFieldsExcluded": true,
|
|
4
4
|
"generatedAt": "1970-01-01T00:00:00.000Z",
|
|
5
5
|
"packageName": "@happyvertical/smrt-reports",
|
|
6
|
-
"packageVersion": "0.57.
|
|
6
|
+
"packageVersion": "0.57.7",
|
|
7
7
|
"sourceManifestPath": "dist/manifest.json",
|
|
8
8
|
"agentDocPath": "AGENTS.md",
|
|
9
9
|
"sourceHashes": {
|
|
10
|
-
"manifest": "
|
|
11
|
-
"packageJson": "
|
|
12
|
-
"agents": "
|
|
13
|
-
"moduleDoc:agents/runtime-report-browser.md": "
|
|
14
|
-
"moduleDoc:agents/runtime-reports.md": "
|
|
10
|
+
"manifest": "53a0b437f4f2dd271f756ebbc02b54c3014cb2b6b5931c23c24188615c46875c",
|
|
11
|
+
"packageJson": "de11a06d3c573ae810768cd82bbbdefc874989002c34cc9a6189b8200f640cc7",
|
|
12
|
+
"agents": "ca3c6a1294ea5caeb0a97a5af04d47f2a5ae1a4358e8f6bae44d95ca2d524758",
|
|
13
|
+
"moduleDoc:agents/runtime-report-browser.md": "4b7d8d3d3766e7ff0ae07b5c78e23a66d2be9dd2f7a3da2dfdc2330bcc9e1516",
|
|
14
|
+
"moduleDoc:agents/runtime-reports.md": "6afffd734071fbe953cc07db6dca205dbc17eba320a98408026dc96aaf825a39",
|
|
15
15
|
"moduleDoc:README.md": "cf7d385aefa3abd225ed4eb2505925155a71b30accb81f8349d86b56064dae2c"
|
|
16
16
|
},
|
|
17
17
|
"exports": [
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"./playground",
|
|
25
25
|
"./refresh",
|
|
26
26
|
"./scheduler",
|
|
27
|
+
"./spec",
|
|
27
28
|
"./state",
|
|
28
29
|
"./svelte"
|
|
29
30
|
],
|
|
@@ -1262,17 +1263,17 @@
|
|
|
1262
1263
|
"polymorphicAssociations": 0,
|
|
1263
1264
|
"uuidColumns": 24
|
|
1264
1265
|
},
|
|
1265
|
-
"agentDoc": "# @happyvertical/smrt-reports\n\nMaterialized aggregate report models and runtime report browser surfaces for SMRT.\n\n## Browser surfaces (#3895)\n\n`./svelte` publishes `SavedReports`, `ReportDetail`, `ReportResult`,\n`ReportConfirmation`, and `ReportPicker`; visual chart renderers come from\n`@happyvertical/smrt-ui/charts`. Keep runtime imports out of this subpath:\nserver report types are type-only imports. See [browser contract](agents/runtime-report-browser.md).\n`pnpm typecheck` includes Svelte diagnostics and `pnpm test` includes browser\ncomponent tests. `./playground` supplies each screen's preview.\n\n## Key Pieces\n\n| Module | Purpose |\n| --- | --- |\n| `SmrtReport` | Abstract report row base with `refreshedAt`, `isStale()`, and manual `refresh()` |\n| decorators | `@report`, grouping decorators, time buckets, and aggregate measure decorators |\n| compiler | Pure `ReportDefinition -> AggregateSpec` compiler and ObjectRegistry adapter |\n| aggregate | Compatibility re-export of the SDK aggregate query builder |\n| refresh | Rebuild and incremental refresh engine with run tracking, watermarks, locks, and tenant scoping |\n| state | Internal `_smrt_report_*` system models for runs, watermarks, locks, schedules, and refresh tasks |\n| scheduler | Cron schedule runner, durable refresh job enqueueing, and `onChange` interceptor registration |\n| adapter | Transport-neutral report descriptor, canonical materialized-row reads, and stable `id` row identity |\n| lifecycle | Tenant-safe freshness, run, lock, failure, and manual refresh preview/apply surfaces |\n| views | Policy-revalidated saved views, snapshot-bound exports, bounded job handoff, and artifact metadata validation |\n| runtime reports | Declarative `RuntimeReportSpec` stored as data (`RuntimeReport`), compiled per principal with field-policy, RBAC and tenant checks; see [agents/runtime-reports.md](agents/runtime-reports.md) |\n\n## Adapter contract\n\n- `buildReportAdapterDescriptor()` returns deterministic, serializable metadata\n for a report surface: a stable resource id, typed persisted report columns,\n the canonical `DataQuerySchema`, and UI-neutral DataTable hints. It must not\n import `smrt-ui` or expose a report-domain class to the consumer.\n- `queryReportMaterializedRows()` owns only the bounded read slice for rows that\n are already materialized. It supports projection, offset/limit paging,\n validated filters, deterministic multi-sort with an `id` tie-breaker, exact\n totals, and dimension facets. At source-query compilation,\n dimension and bucket filters compile to `WHERE`, aggregate-measure filters\n compile to `HAVING`, and mixed `OR`/`NOT` filter scopes fail closed.\n- `id` is the only row identity. It must be a non-empty persisted string and is\n never replaced by a display index or page position.\n- The descriptor is an exposure boundary. Sensitive/secret fields, fields with\n `readPermission`, and transient, system, or non-column fields fail closed and\n do not become public columns when no principal is available.\n- `tenantScoped`/`tenantField` reflect actual registered tenant metadata. A\n `tenantScope` option only contributes to the stable resource id; it is not\n authorization. Pass the same `adapter` options to\n `queryReportMaterializedRows()` that were used to build the selected\n descriptor, so results and background tasks retain that stable resource id.\n The default query path resolves the registered collection via `ObjectRegistry`,\n so normal collection tenancy interceptors apply. An injected collection is\n application-owned and must preserve the same boundary.\n- `refresh` is a declaration, not execution. It describes configured mode,\n triggers, positive-TTL stale-read behavior, and a permissioned/audited action\n with preview/apply phases. The adapter remains read-only, while\n `getReportLifecycle()` provides an explicit, tenant-safe lifecycle snapshot\n and `previewReportRefresh()` / `applyReportRefresh()` delegate authorization,\n audit, and queueing through an application action host. Only a registered\n `SmrtReportCollection` may synchronously refresh stale reads, when its TTL is\n positive and the report is not manual.\n- `views` accepts no authority. Persisted views must be normalized again through\n the current descriptor before restoring them, so changed column policy or a\n changed report definition fails closed. Treat unversioned persisted layouts as\n legacy v0 and migrate them to v1 before normalization; unknown versions must\n fail rather than being inferred. Export snapshots retain the canonical\n query fingerprint, projection, sort, as-of/freshness state, exact row count,\n and the fixed principal/tenant/report-definition/field-policy inheritance\n contract. A snapshot needs an application-host-issued opaque binding and an\n explicit offset-page read plan: workers advance it from offset zero instead\n of reusing a visible page. Preview, apply, worker, and artifact-serving\n boundaries must call the validators, including the host's immutable-snapshot\n assertion; application hosts own authorization, audit records, durable\n storage, download tokens, and queue execution.\n\n## Runtime reports (#3711)\n\nA runtime report is data, not code: `parseRuntimeReportSpec()` accepts a closed\ngrammar (no SQL, expressions, joins, tables, or tenants), and\n`compileRuntimeReportSpec()` resolves it against a server-owned source\nallow-list (including optional `fields`/`excludeFields`), the ObjectRegistry field policy, the live principal's permissions,\nand an explicit fail-closed tenant predicate. Stored `RuntimeReport` specs are\nre-compiled for the running principal on every run, and result rows are never\npersisted. Assistant tools are in `@happyvertical/smrt-chat`. The full\ncontract, authority model, and deferred work are in\n[agents/runtime-reports.md](agents/runtime-reports.md).\n\n## Recipes (#3719)\n\n`src/recipes.ts` declares `reports.materialized` (`MaterializedReportsRecipe`),\nemitted into the built `manifest.json` and `smrt-knowledge.json` `recipes`. It\nbrings only the internal refresh bookkeeping tables (runs, watermarks, locks,\nschedules, refresh tasks); an app's own `@report` classes are not listed because\nthey belong to the app. Those tables have no REST or MCP surface, so the recipe\nhas no `nav`. It declares `runtime: 'server'` (SQL aggregation, jobs) and no\n`surfaces`: materialized reports do not yet have a browser surface. Runtime\nreport browser components stay on the `./svelte` subpath, while\n`RuntimeReportsRecipe` names their route, widget, and options-editor exports.\n\nUser-facing help is `src/materialized.recipe.md` (#3591). It explains how the\nassistant reads declared reports (`data.discover`/`data.inspect` and\n`reports.query`/`reports.refresh` from `@happyvertical/smrt-agents`) and how\nruntime reports (`reports.runtime.*` in `@happyvertical/smrt-chat`) differ: live,\nnever stored, saved only after a person confirms. Keep that split accurate when\neither tool set changes. `{field:...}` references need a `@field({ description })`\non `state.ts` so the glossary can explain them. `src/__tests__/recipes.test.ts`\nruns the real scan, manifest and generation passes in memory and renders the help.\nSee [core recipes](../core/agents/recipes.md).\n\n## Conventions\n\n- Report cache tables are normal `@smrt()` tables. Runtime refresh must not create schema.\n- Store report metadata under field `_meta.__report`; scanner and runtime decorators must stay aligned.\n- Keep SQL generation portable. Use the SDK `buildAggregate()`/`bucketExpr()` helpers for time buckets and `$N` placeholders.\n- Do not add a local aggregate SQL builder here; the implementation lives in `@happyvertical/sql`.\n- Refresh runtime tables are schema-managed. Runtime refresh must fail clearly when `_smrt_report_runs`, `_smrt_report_watermarks`, or `_smrt_report_locks` have not been migrated.\n- Incremental refresh requires a source watermark column (default `updatedAt`) and soft-delete column (default `deletedAt`); it recomputes affected groups and deletes empty report groups instead of applying aggregate deltas.\n- Raw aggregate refreshes must explicitly filter `tenant_id`; the tenancy interceptor only protects normal collection reads.\n- Scheduled/on-change refreshes enqueue `SmrtReportRefreshTask.run()` through `@happyvertical/smrt-jobs`; do not add a separate report queue.\n- `SmrtReportCollection` is a framework collection base (core's `SMRT_COLLECTION_BASE_NAMES`): a report collection never owns its model's table, even when an app manifest attributes the two to different packages. `pnpm test:postgres` runs the `*.optional.test.ts` lane (#3110).\n\n## Package registration\n\n`src/__smrt-register__.ts` embeds the provider manifest during library builds.\nImport it before model decorators, including model-bearing subpaths (`state`\nand `scheduler`), so consumer SSR bundles retain reports-qualified identities.\nThe bundle gate executes these public entries in a fresh consumer process.\nAudit #3525 found no other published domain model package missing its shim;\npackages without one contain framework utilities or example/test decorators.\n\n## Schedule lifecycle\n\n`tenantFanout: 'discover'` resolves non-null tenants in the source and existing\nmaterialization at execution time only for signed global scheduled maintenance.\nInclude materialized scopes so rebuilds clear groups after their last source\nrow is deleted; discovery does not change incremental watermark semantics. Empty discovery must not call\nrefresh with an empty tenant array, which would select the global slice.\nSchedule provisioning preserves existing state. Hosts bind terminal job events\nwith `ReportScheduleRunner.bindTaskRunner()` and dispose the returned binding\non shutdown; see [scheduled refresh lifecycle](README.md#scheduled-refresh-lifecycle).\n\n## Runtime server surfaces (#3878)\n\n`runtime-server.ts` owns the framework-neutral confirmation handler, current\nprincipal run/archive helpers and chart loader. Source allow-lists come from\n`packages.reports.runtime.sources`; no configuration means no sources. Never\naccept identity or source configuration from JSON. The RuntimeReport run/archive\nmethods reuse read/create grants through `operationPermissions`, including the\narchive UPDATE RLS binding. `RuntimeReportsRecipe` declares nav, route and\n`runtime-report-chart` surfaces, and server runtime. The chart loader receives\n`reportPrincipal` only from authenticated host context. See\n[runtime contract](agents/runtime-reports.md) and\n[browser surfaces](agents/runtime-report-browser.md).\n",
|
|
1266
|
+
"agentDoc": "# @happyvertical/smrt-reports\n\nMaterialized aggregate report models and runtime report browser surfaces for SMRT.\n\n## Browser surfaces (#3895)\n\n`./svelte` publishes `SavedReports`, `ReportDetail`, `ReportResult`,\n`ReportConfirmation`, and `ReportPicker`; visual chart renderers come from\n`@happyvertical/smrt-ui/charts`. Keep runtime imports out of this subpath:\nserver report types are type-only imports. See [browser contract](agents/runtime-report-browser.md).\n`pnpm typecheck` includes Svelte diagnostics and `pnpm test` includes browser\ncomponent tests. `./playground` supplies each screen's preview.\n\n## Key Pieces\n\n| Module | Purpose |\n| --- | --- |\n| `SmrtReport` | Abstract report row base with `refreshedAt`, `isStale()`, and manual `refresh()` |\n| decorators | `@report`, grouping decorators, time buckets, and aggregate measure decorators |\n| compiler | Pure `ReportDefinition -> AggregateSpec` compiler and ObjectRegistry adapter |\n| aggregate | Compatibility re-export of the SDK aggregate query builder |\n| refresh | Rebuild and incremental refresh engine with run tracking, watermarks, locks, and tenant scoping |\n| state | Internal `_smrt_report_*` system models for runs, watermarks, locks, schedules, and refresh tasks |\n| scheduler | Cron schedule runner, durable refresh job enqueueing, and `onChange` interceptor registration |\n| adapter | Transport-neutral report descriptor, canonical materialized-row reads, and stable `id` row identity |\n| lifecycle | Tenant-safe freshness, run, lock, failure, and manual refresh preview/apply surfaces |\n| views | Policy-revalidated saved views, snapshot-bound exports, bounded job handoff, and artifact metadata validation |\n| runtime reports | Declarative `RuntimeReportSpec` stored as data (`RuntimeReport`), compiled per principal with field-policy, RBAC and tenant checks; see [agents/runtime-reports.md](agents/runtime-reports.md) |\n\n## Adapter contract\n\n- `buildReportAdapterDescriptor()` returns deterministic, serializable metadata\n for a report surface: a stable resource id, typed persisted report columns,\n the canonical `DataQuerySchema`, and UI-neutral DataTable hints. It must not\n import `smrt-ui` or expose a report-domain class to the consumer.\n- `queryReportMaterializedRows()` owns only the bounded read slice for rows that\n are already materialized. It supports projection, offset/limit paging,\n validated filters, deterministic multi-sort with an `id` tie-breaker, exact\n totals, and dimension facets. At source-query compilation,\n dimension and bucket filters compile to `WHERE`, aggregate-measure filters\n compile to `HAVING`, and mixed `OR`/`NOT` filter scopes fail closed.\n- `id` is the only row identity. It must be a non-empty persisted string and is\n never replaced by a display index or page position.\n- The descriptor is an exposure boundary. Sensitive/secret fields, fields with\n `readPermission`, and transient, system, or non-column fields fail closed and\n do not become public columns when no principal is available.\n- `tenantScoped`/`tenantField` reflect actual registered tenant metadata. A\n `tenantScope` option only contributes to the stable resource id; it is not\n authorization. Pass the same `adapter` options to\n `queryReportMaterializedRows()` that were used to build the selected\n descriptor, so results and background tasks retain that stable resource id.\n The default query path resolves the registered collection via `ObjectRegistry`,\n so normal collection tenancy interceptors apply. An injected collection is\n application-owned and must preserve the same boundary.\n- `refresh` is a declaration, not execution. It describes configured mode,\n triggers, positive-TTL stale-read behavior, and a permissioned/audited action\n with preview/apply phases. The adapter remains read-only, while\n `getReportLifecycle()` provides an explicit, tenant-safe lifecycle snapshot\n and `previewReportRefresh()` / `applyReportRefresh()` delegate authorization,\n audit, and queueing through an application action host. Only a registered\n `SmrtReportCollection` may synchronously refresh stale reads, when its TTL is\n positive and the report is not manual.\n- `views` accepts no authority. Persisted views must be normalized again through\n the current descriptor before restoring them, so changed column policy or a\n changed report definition fails closed. Treat unversioned persisted layouts as\n legacy v0 and migrate them to v1 before normalization; unknown versions must\n fail rather than being inferred. Export snapshots retain the canonical\n query fingerprint, projection, sort, as-of/freshness state, exact row count,\n and the fixed principal/tenant/report-definition/field-policy inheritance\n contract. A snapshot needs an application-host-issued opaque binding and an\n explicit offset-page read plan: workers advance it from offset zero instead\n of reusing a visible page. Preview, apply, worker, and artifact-serving\n boundaries must call the validators, including the host's immutable-snapshot\n assertion; application hosts own authorization, audit records, durable\n storage, download tokens, and queue execution.\n\n## Runtime reports (#3711)\n\nA runtime report is data, not code: `parseRuntimeReportSpec()` accepts a closed\ngrammar (no SQL, expressions, joins, tables, or tenants), and\n`compileRuntimeReportSpec()` resolves it against a server-owned source\nallow-list (including optional `fields`/`excludeFields`), the ObjectRegistry field policy, the live principal's permissions,\nand an explicit fail-closed tenant predicate. Stored `RuntimeReport` specs are\nre-compiled for the running principal on every run, and result rows are never\npersisted. Assistant tools are in `@happyvertical/smrt-chat`. The full\ncontract, authority model, and deferred work are in\n[agents/runtime-reports.md](agents/runtime-reports.md).\n\n`./spec` (#4100) is the browser-safe half: the grammar, `runtimeReportSpecDigest`\n(Web Crypto twin of the server-only `runtimeReportSpecHash`) and\n`runRuntimeReportInMemory()`, which evaluates a spec over caller-held rows with\nthe compiler's own rules (`runtime-plan.ts`). It is a preview and test runner,\nnever an authority boundary. `spec-entry.test.ts` fails if that entry reaches a\nNode built-in or any package module but `@happyvertical/smrt-core/smrt-error`;\n`runtime-memory-parity.test.ts` holds it to the SQL path. Source descriptions\ncarry time and grouping hints and `./spec` exports the time-language helpers\n(`runtime-dimensions.ts`, `runtime-time.ts`); see the runtime contract.\n\n## Recipes (#3719)\n\n`src/recipes.ts` declares `reports.materialized` (`MaterializedReportsRecipe`),\nemitted into the built `manifest.json` and `smrt-knowledge.json` `recipes`. It\nbrings only the internal refresh bookkeeping tables (runs, watermarks, locks,\nschedules, refresh tasks); an app's own `@report` classes are not listed because\nthey belong to the app. Those tables have no REST or MCP surface, so the recipe\nhas no `nav`. It declares `runtime: 'server'` (SQL aggregation, jobs) and no\n`surfaces`: materialized reports do not yet have a browser surface. Runtime\nreport browser components stay on the `./svelte` subpath, while\n`RuntimeReportsRecipe` names their route, widget, and options-editor exports.\n\nUser-facing help is `src/materialized.recipe.md` (#3591). It explains how the\nassistant reads declared reports (`data.discover`/`data.inspect` and\n`reports.query`/`reports.refresh` from `@happyvertical/smrt-agents`) and how\nruntime reports (`reports.runtime.*` in `@happyvertical/smrt-chat`) differ: live,\nnever stored, saved only after a person confirms. Keep that split accurate when\neither tool set changes. `{field:...}` references need a `@field({ description })`\non `state.ts` so the glossary can explain them. `src/__tests__/recipes.test.ts`\nruns the real scan, manifest and generation passes in memory and renders the help.\nSee [core recipes](../core/agents/recipes.md).\n\n## Conventions\n\n- Report cache tables are normal `@smrt()` tables. Runtime refresh must not create schema.\n- Store report metadata under field `_meta.__report`; scanner and runtime decorators must stay aligned.\n- Keep SQL generation portable. Use the SDK `buildAggregate()`/`bucketExpr()` helpers for time buckets and `$N` placeholders.\n- Do not add a local aggregate SQL builder here; the implementation lives in `@happyvertical/sql`.\n- Refresh runtime tables are schema-managed. Runtime refresh must fail clearly when `_smrt_report_runs`, `_smrt_report_watermarks`, or `_smrt_report_locks` have not been migrated.\n- Incremental refresh requires a source watermark column (default `updatedAt`) and soft-delete column (default `deletedAt`); it recomputes affected groups and deletes empty report groups instead of applying aggregate deltas.\n- Raw aggregate refreshes must explicitly filter `tenant_id`; the tenancy interceptor only protects normal collection reads.\n- Scheduled/on-change refreshes enqueue `SmrtReportRefreshTask.run()` through `@happyvertical/smrt-jobs`; do not add a separate report queue.\n- `SmrtReportCollection` is a framework collection base (core's `SMRT_COLLECTION_BASE_NAMES`): a report collection never owns its model's table, even when an app manifest attributes the two to different packages. `pnpm test:postgres` runs the `*.optional.test.ts` lane (#3110).\n\n## Package registration\n\n`src/__smrt-register__.ts` embeds the provider manifest during library builds.\nImport it before model decorators, including model-bearing subpaths (`state`\nand `scheduler`), so consumer SSR bundles retain reports-qualified identities.\nThe bundle gate executes these public entries in a fresh consumer process.\nAudit #3525 found no other published domain model package missing its shim;\npackages without one contain framework utilities or example/test decorators.\n\n## Schedule lifecycle\n\n`tenantFanout: 'discover'` resolves non-null tenants in the source and existing\nmaterialization at execution time only for signed global scheduled maintenance.\nInclude materialized scopes so rebuilds clear groups after their last source\nrow is deleted; discovery does not change incremental watermark semantics. Empty discovery must not call\nrefresh with an empty tenant array, which would select the global slice.\nSchedule provisioning preserves existing state. Hosts bind terminal job events\nwith `ReportScheduleRunner.bindTaskRunner()` and dispose the returned binding\non shutdown; see [scheduled refresh lifecycle](README.md#scheduled-refresh-lifecycle).\n\n## Runtime server surfaces (#3878)\n\n`runtime-server.ts` owns the framework-neutral confirmation handler, current\nprincipal run/archive helpers and chart loader. Source allow-lists come from\n`packages.reports.runtime.sources`; no configuration means no sources. Never\naccept identity or source configuration from JSON. The RuntimeReport run/archive\nmethods reuse read/create grants through `operationPermissions`, including the\narchive UPDATE RLS binding. `RuntimeReportsRecipe` declares nav, route and\n`runtime-report-chart` surfaces, and server runtime. The chart loader receives\n`reportPrincipal` only from authenticated host context. See\n[runtime contract](agents/runtime-reports.md) and\n[browser surfaces](agents/runtime-report-browser.md).\n",
|
|
1266
1267
|
"moduleDocs": [
|
|
1267
1268
|
{
|
|
1268
1269
|
"path": "agents/runtime-report-browser.md",
|
|
1269
1270
|
"module": "runtime-report-browser",
|
|
1270
|
-
"content": "# Runtime report browser surfaces (#3895)\n\nThe browser entry is `@happyvertical/smrt-reports/svelte`. It imports visual and\nform primitives from smrt-ui, never smrt-svelte or the reports server barrel.\n`@happyvertical/smrt-ui/charts` owns the five shared renderers; the overview\nchart and report results both consume it.\n\n- `SavedReports`:
|
|
1271
|
+
"content": "# Runtime report browser surfaces (#3895)\n\nThe browser entry is `@happyvertical/smrt-reports/svelte`. It imports visual and\nform primitives from smrt-ui, never smrt-svelte or the reports server barrel.\n`@happyvertical/smrt-ui/charts` owns the five shared renderers; the overview\nchart and report results both consume it.\n\n- `SavedReports`: tenant-shared saved reports as a responsive grid of\n `SavedReportCard`s (title opening the report, a one-line description from\n `describeReport`, a headline figure and sparkline from a run, saved/updated\n time), Everyone's/Mine and Show archived filters (smrt-ui `SegmentedControl`,\n `Switch`), \"New report\", an empty state, and Archive in each card's \"more\"\n menu behind a confirmation. `variant: 'section'` is the Reports section page.\n The host resolves author ids (`authorLabel`), passes source labels\n (`sources`), and supplies an archive capability hint; the server authorizes\n every archive again. Each shown report runs once (three at a time).\n- \"New report\" and Edit call smrt-ui `requestAssistant` (the dock fills its\n composer); with no assistant on the page the screen says where to ask.\n- `ReportDetail`: a summary header (description, source, groupings, period\n with its dates, measures, filters, who saved it, last run), then the result\n run afresh on open and each re-run. Primary action by state: Edit, Try again\n after a failed run, Restore when archived; Export CSV (formatted,\n formula-safe) beside it; Re-run and Archive in the \"more\" menu. The transport is\n principal-scoped; replace it when viewer/tenant changes. Pending old\n responses are discarded, and result rows live only in component state.\n- `ReportResult`: validates the result shape and safe integers. `full` (a\n report's page): a Chart/Table switch, a measure switch, headline figures\n (total for sums and counts, average per bucket, peak) and a tall smrt-ui\n `Chart` with a value axis and keyboard/pointer readout. `compact` (preview\n card): a quiet table toggle. Tables format money and time buckets. Money\n fields use integer minor units and the host's ISO currency (default USD).\n- `saved-reports` widget (`SavedReportsWidget`, recipe `sectionDefault`): the\n Reports section page in any host rendering data widgets; it reads through\n the shared browser client unless the host passes `client`.\n- `ReportConfirmation`: shows the source label, groupings, measures,\n filters, and a bounded preview. Approve requires a trusted local click and\n posts the exact displayed `{ spec, specHash }` to the proposal's same-origin\n `confirmPath` once while pending. Decline never calls the server. The server\n recompiles as the confirming principal and idempotently saves the approved\n spec; the hash carries no authority by itself.\n- Answered state (#4100): after Approve or Decline the card shows an outcome\n line (\"Report saved · Open report\", \"Declined — nothing saved\") instead\n of buttons; pass `outcome` from the transcript so a reloaded card does too.\n `fields` (a source descriptor's names, labels, formats) labels groupings,\n buckets (\"Issue date by month\") and money filters; measures use the result's\n column labels. `ReportResult` labels time buckets by granularity\n (smrt-ui `formatTimeBucket`) and keeps the table toggle quiet.\n- `ReportPicker`: labelled fields (smrt-ui `FormGroup`) offering readable\n active reports and their measures and groupings by name, not alias;\n changing the report clears dependent choices.\n\n`createRuntimeReportsHttpClient()` implements the generated same-origin reads,\nthe enveloped `run`/`archive` actions, and the confirmation POST. It has no\ndatabase, tenant, or permission authority. Successful run timestamps live only\nin that browser client's session map; route hosts include an opaque active\ntenant/session scope so hints are discarded when the principal context changes. Omit the client (or set\n`serverAvailable={false}` on a route component) for a static host: the screens\nexplain that reports need a server and make no requests.\n\n`runtimeReportToolResultComponent` is the reports adapter for AssistantDock's\ngeneric component seam. Recipe routes export `RuntimeReportsRoute` and\n`RuntimeReportDetailRoute`; the `runtime-report-chart` surface exports its\nrenderer and dependent report/measure/dimension editor. The server host builds\nthe chart loader context from request-scoped `reportPrincipal`; widget options\nnever carry identity, permissions, tenant, or database authority.\n\nThe `./playground` entry has saved-list, detail, confirmation, picker, empty and\nunavailable previews. They use deterministic sample data, not a production\nbackend. All component copy registers through `smrt-ui/i18n`.\n\nThe smrt planner (#4100) renders `ReportConfirmation`, `SavedReports` and\n`ReportDetail` with its own `RuntimeReportsClient` over sample data and the\nin-memory runner from `./spec`; its `confirm` is a browser save, not this\npackage's confirmation route.\n\nThe template reference application exercises the generic dock selector, a real\ntrusted browser approval click, authenticated confirmation and generated reads,\ndetail execution, and the recipe-registered overview loader/renderer without\nmocking an endpoint.\n"
|
|
1271
1272
|
},
|
|
1272
1273
|
{
|
|
1273
1274
|
"path": "agents/runtime-reports.md",
|
|
1274
1275
|
"module": "runtime-reports",
|
|
1275
|
-
"content": "# Runtime reports (#3711)\n\nReports the assistant (or any caller) defines at runtime from a user request.\nA report is a **declarative spec stored as data**; there is no codegen, no new\ntable per report, and no SQL, expression, join or raw-identifier syntax in the\ngrammar. Declared (`@report`) reports are unchanged and remain the way to get a\n**materialized** report.\n\n## Files\n\n| File | Role |\n| --- | --- |\n| `src/runtime-spec.ts` | `RuntimeReportSpec` grammar, strict parser, limits, stable hash |\n| `src/runtime-compiler.ts` | `compileRuntimeReportSpec()`, `describeRuntimeReportSource()`, `runRuntimeReport()` |\n| `src/runtime-server.ts` | Same-origin confirmation, principal-bound run/archive, chart loader |\n| `src/runtime-report.ts` | `RuntimeReport` model (`runtime_reports`), `saveRuntimeReport()`, list/get/archive, `runStoredRuntimeReport()` |\n\nAssistant tools live in `@happyvertical/smrt-chat` (`createRuntimeReportTools()`,\n`src/runtime-report-tools.ts`).\n\n\nSource definitions may set `fields` (an allow-list) and `excludeFields` (a deny-list).\nBoth use exact public model field names. Omitted `fields` retains all eligible\nfields; `fields: []` exposes none. Exclusions win, and neither option bypasses\nmodel sensitivity, field permissions, or tenant restrictions. Invalid lists and\nunknown names reject the source with `unsupported_source`, including misspelled\nexclusions. Descriptions, assistant tools, confirmation and saved-report runs\nresolve this same policy on every invocation.\n\nStandard timestamps have one public spelling: `createdAt` and `updatedAt`.\nSnake-case `created_at`/`updated_at` remain physical SQL columns, not accepted\nspec or configuration field names. Existing saved specs using those aliases must\nbe proposed again with canonical names and confirmed. Model restrictions on any\nalias protect the whole physical column; host exclusions also cover aliases.\n\n```typescript\n{ id: 'incidents', className: 'Incident', collection: 'incidents',\n fields: ['id', 'title', 'createdAt', 'status'],\n excludeFields: ['signatureAssetId'] }\n```\nThe example assumes `signatureAssetId` is a declared model field; exclusions\nare validated even if an allow-list already omits that field.\n\n## Spec\n\n`version: 1`, `title`, optional `description`, `source` (a server-owned source\nid), `dimensions[]` (`field`, `as?`, `bucket?`), `measures[]` (`fn`: `count`,\n`countDistinct`, `sum`, `avg`, `min`, `max`; `field?`; `as?`), `filters[]`\n(AND-ed; ops `eq ne gt gte lt lte in notIn contains isNull isNotNull`),\n`having[]` (measure alias, numeric compare), `sort[]`, `limit` (1-1000, default\n100) and a `chart` hint (`table|bar|line|pie|stat`, `x`, `y[]`). Unknown keys\nat any level are rejected. Bounds (entries, string length, `in` list size,\nalias charset, reserved words) are in `RUNTIME_REPORT_LIMITS`.\n\nThe parser normalizes defaults and derives aliases, so equal specs hash equally\n(`runtimeReportSpecHash`). The hash is what a human confirmation binds to.\n\n## Authority model\n\nA spec carries **no authority**. Everything is decided at compile time from\ninputs the caller cannot supply through the spec:\n\n- **Sources.** `RuntimeReportCompileContext.sources` is a server allow-list of\n `{ id, className, collection }`. The spec names an id; unknown and\n not-offered answer identically (`unknown_source`). `authorizeSource` is the\n host's RBAC hook (the chat tools call `run.assertOperation(collection,\n 'read')`) and runs before any field is enumerated. A host should also narrow\n `sources` to those the principal may read before compiling (the chat tools do),\n because `authorizeSource` only runs for an id that is in the list: otherwise\n an RBAC refusal for a configured id and `unknown_source` for an absent one are\n different answers, and a caller can enumerate the configured source ids. `collection` is the\n permission-catalog collection **slug** (the `<collection>` of\n `<collection>.read`, for example `runtimereports`), or the registered model\n class, which resolves to that slug through the catalog's own helper. It is\n never a class name string: `Invoice` derives `Invoice.read`, which no\n catalog contains, so every read is denied and the source is silently not\n offered.\n- **Field policy.** Names are resolved from the ObjectRegistry, never from the\n spec. Not nameable: `sensitive` / `sensitivity: sensitive|secret` fields,\n `readPermission` fields unless `context.permissions` holds that permission,\n `transient`, `json`/relationship fields, `_`-prefixed internals and the tenant\n column. A hidden field is reported exactly like an absent one\n (`unknown_field`), so the compiler is not an existence oracle.\n- **Types.** `sum`/`avg` need numeric fields, `min`/`max` numeric or datetime,\n `bucket` needs datetime, `contains` needs text, id fields accept only UUIDs\n and equality-style ops. Values are coerced to the field type, then bound.\n- **Tenancy.** Raw aggregates bypass collection interceptors, so the compiler\n adds the tenant predicate itself (same column resolution as refresh).\n Tenant-scoped source with no tenant in scope reads only NULL-tenant rows;\n there is no cross-tenant option and `withSystemContext()`/super-admin bypass\n are deliberately not honored. Sources without a tenant column are global by\n definition. `deletedAt` and STI-child discriminators are applied when the\n source has them.\n- **SQL safety.** The plan is an `AggregateSpec` executed by the SDK\n `buildAggregate()`: identifiers are registry-derived and re-validated by the\n builder, values are `$N` parameters, and output aliases are prefixed `r_`\n inside the SQL so an alias can never shadow a source column.\n- **Re-validation.** A stored report is re-parsed (hash-checked) and\n re-compiled against the **running** principal on every run, so policy changes\n apply immediately and a viewer without a permission cannot run a report saved\n by someone who had it.\n- **Stored-report storage.** The tenancy interceptor filters by the AMBIENT\n tenant, while compilation uses the principal's tenant. The chat tools bind the\n two: they enter the principal's tenant context for `list`/`get`/`save` (as the\n data-surface guard does), refuse when an ambient tenant disagrees with the\n principal (on `apply`, before the human is asked to confirm, #3768), require\n a tenant for any stored-report use, and pass the principal\n tenant as an explicit owner filter (`getRuntimeReport`/`listRuntimeReports`\n accept `tenantId`) that still holds under a system context.\n\n`listRuntimeReports` also accepts exact `createdByUserId` and `specHash`\npredicates. They are ANDed with status and explicit/ambient tenant filters before\nlimiting results, so hosts can list a principal's saved reports or find a previous\nsave of the compiled normalized spec without retrieving other authors' reports.\nThese filters never replace authorization. See the\n[list-filter contract and test matrix](runtime-report-list-filters.md).\n\n## Storage and surface\n\n`RuntimeReport` is `@TenantScoped({ mode: 'required' })` with `spec` (normalized\nJSON text), `specHash`, denormalized `title`/`description`/`sourceId`,\n`status` (`active|archived`) and `createdByUserId`. `validateBeforeSave()` parses\nwhatever was written and re-derives every denormalized column, so columns\ncannot disagree with the spec. `getSpec()` throws if the JSON no longer matches\n`specHash` (out-of-band edit). Adopting apps need a `db:migrate` for the new\n`runtime_reports` table; runtime never creates schema. Existing deployments also\nrun `db:migrate` for the confirmation lookup index `idx_runtime_reports_confirm`\nbefore enabling browser confirmation.\n\n**Invariant: no row is inserted, and no spec/title/source/description/author is\nchanged, except through the confirmed save.** It is enforced in the model layer,\nnot by which surfaces exist. `validateBeforeSave()` refuses (`confirmation_required`,\n403) every insert, and every update that changes those columns, unless the\ninstance carries a confirmation proof. The proof is a symbol-keyed constructor\noption plus a module-private `WeakMap`; only `saveRuntimeReport()` can mint it,\nand only when `confirmedSpecHash` equals the compiled plan's hash (the value\nhanded to the application's `RuntimeReportConfirmationHost`). It is single use\nand tied to that exact spec hash. A REST body, a manifest tool call or\n`new RuntimeReport({...}).save()` cannot carry it, so it is refused whatever\nsurface delivered it. A reused id on an insert is refused the same way, so it\ncannot overwrite a stored spec. Archiving or unarchiving (a `status` change with\nthe stored columns untouched) is allowed for an authorised writer.\n\n**Exposed operations** (these decide the permission catalog and RLS grants):\n\n| Surface | Operations |\n| --- | --- |\n| REST (`api`) | `list`, `get`, `create`, `run`, `archive` |\n| CLI | `list`, `get`, `run`, `archive` |\n| MCP | `list`, `get`, `run`, `archive` |\n\nThe permission catalog therefore holds exactly `<collection>.read` and\n`<collection>.create` for `RuntimeReport` (the collection slug is\n`runtimereports`). `update` and `delete` exist on no surface, so they are not in\nthe catalog, not grantable to a role and not nameable in a persona's\n`allowedTools`. REST `create` exists only so the catalog knows the operation the\nconfirmed save performs (`assertOperation(RuntimeReport, 'create')`); its body is\nalways refused by the invariant above. The generic manifest tool dispatcher in\n`@happyvertical/smrt-chat` additionally never offers or runs a write operation on\n`RuntimeReport` (`isRuntimeReportWriteOperation`), so the assistant persists a\nreport only through `reports.runtime.define` (apply).\n\n**Result rows are never persisted.** A result computed for one principal must\nnot be served to another, so the table stores definitions only.\n\n## Why not materialize\n\nDeclared reports materialize into a build-time `@smrt()` table and refresh\nthrough the lock/watermark engine. Runtime schema creation is forbidden here, so\na runtime spec runs as a bounded live aggregate on the same `AggregateSpec`\ncompile target instead. Promoting a proven runtime spec to a declared,\nmaterialized `@report` (codegen plus a migration) is a maintainer decision and\nis tracked as a follow-up.\n\n## Money\n\nMoney fields are integer minor units; `sum`/`min`/`max` keep the integer type and\nthe source field's `format` hint is carried onto the result column. Integer\nresults beyond the JavaScript safe range throw `invalid_result` rather than\nlosing precision. `avg` is decimal.\n\n## Assistant and browser flow (#3878)\n\n`reports.runtime.sources` describes fields available to the assistant principal.\n`reports.runtime.define` with `phase: 'preview'` compiles and runs a bounded\nsample. `phase: 'apply'` requires the preview's exact normalized `specHash`.\nWithout an in-process confirmation host it returns:\n\n```ts\n{ status: 'awaiting_confirmation', specHash, spec, sourceLabel, preview,\n confirmPath: '/api/_reports/runtime/confirm' }\n```\n\nNothing is saved by that response, and model-supplied consent is ignored. The\nbrowser shows the proposal and only a person's approval posts `{ spec, specHash }`\nto `createRuntimeReportConfirmHandler()`. The handler checks same origin, the\nverified session user and tenant, `runtimereports.create`, the normalized hash,\nand compilation under the **confirming** principal's current permissions.\nAnother principal may approve the same public spec only under their own\npermissions and tenant; a hash is data, not a transferable authorization token.\n\nThe template mounts `POST /api/_reports/runtime/confirm`. Hosts pass the verified\nprincipal and the request's database (including the RLS transaction), never\nbody-supplied identity. Success is `201 { id, specHash, title }`; a retry of an\nactive definition with the same principal/hash returns the same response with\n200. Compilation happens again even on retries. Concurrent approvals use core's\ntransactional `runOnce` claim, keyed by tenant, principal and normalized spec.\nA failed write rolls back the claim; an audit\ncallback failure returns a generic 500 and a retry finds the already saved row.\nNo result rows are stored in the idempotency record. After archiving, approving\nthe same definition returns 409 `report_archived`; restore it through the archive\naction before retrying.\n\nErrors are JSON `{ code, message }`: 401 without a session; 403 for cross-origin,\nmissing permission, mismatched ambient tenant, or an active retry invalidated by\ncurrent source/field access; 409 for an archived retry; 422 for a malformed new\nspec or `spec_hash_mismatch`; generic 500 for unexpected provider failures. There is\nno cross-tenant or system bypass. Configure an optional `audit` callback on the\nfactory to receive confirmed principal/hash/report identity and whether reused.\n\nFor CLI and other in-process hosts, `RuntimeReportConfirmationHost.confirmSave()`\nremains available: it must resolve only after a person approves that exact hash.\nThe single-use model proof is unchanged in both paths. The assistant tools use\nthe persona's fail-closed `allowedTools` gates.\n\n## Server configuration and actions\n\nConfigure `packages.reports.runtime.sources` in `smrt.config.ts`:\n\n```ts\npackages: {\n reports: { runtime: { sources: [\n { id: 'invoices', className: '@acme/app:Invoice', collection: 'invoices', label: 'Invoices' }\n ] } }\n}\n```\n\nAn absent source list exposes nothing. A source's `collection` is a catalog slug\nand requires `<collection>.read`; the server narrows the allow-list before\ncompiling. Give the assistant the same server-owned source definitions. The\nconfirm factory can instead take explicit `{ sources, audit? }` options.\n\n`POST /api/runtimereports/:id/run` takes no body and returns\n`{ action: 'run', result: RuntimeReportResult }`. Its CLI/MCP counterparts call\nthe same model action. It requires `runtimereports.read`, reloads the definition\nin the principal's tenant, and recompiles on every call. Tenant peers can run\nshared reports; use `createdByUserId` for an Only mine list filter. Missing and\nforeign-tenant ids return 404; revoked source/field access returns 403; archived\nreports return 409 `report_archived`; invalid results return 422. Rows stay\nephemeral and integer money stays in minor units.\n\n`POST /api/runtimereports/:id/archive` takes `{ archived: boolean }` and returns\n`{ action: 'archive', result: { id, status } }`. It requires\n`runtimereports.create`, changes status only, and\nrepeating the same state does not write again. `operationPermissions` metadata\naliases run to read and archive to create consistently across generated routes,\nCLI/MCP guards and the permission catalog. The archive alias adds SELECT and\nUPDATE SQL-policy bindings to create: the authorized action must look up the\nsame-tenant row before changing its status. Adopted PostgreSQL RLS policies must\nbe regenerated. Neither `.run`, `.archive`, `.update` nor `.delete` becomes a\nnew grantable permission for this model.\n\n`loadRuntimeReportChart(options, context)` is the server loader for the dependent\nbrowser recipe widget. Options are `{ reportId, measure, dimension? }`; the host\nsupplies `context.reportPrincipal` from its authenticated request and optionally\n`currency`. It runs afresh as the viewer and returns structural chart data:\n`{ points: [{label, value}], format, currency?, href }`. The loader has no\nsmrt-svelte dependency and receives no authority from widget options.\n\n## Recipe UI\n\n`reports.runtime` declares the RuntimeReport model, Reports navigation, the\n`/reports` routes and `runtime-report-chart` widget. The widget options are only\n`{ reportId, measure, dimension? }`; the authenticated server host supplies the\nloader's `reportPrincipal`. Static hosts render the Reports route unavailable.\nRename, scheduling and manual report construction remain deferred.\n"
|
|
1276
|
+
"content": "# Runtime reports (#3711)\n\nReports the assistant (or any caller) defines at runtime from a user request.\nA report is a **declarative spec stored as data**; there is no codegen, no new\ntable per report, and no SQL, expression, join or raw-identifier syntax in the\ngrammar. Declared (`@report`) reports are unchanged and remain the way to get a\n**materialized** report.\n\n## Files\n\n| File | Role |\n| --- | --- |\n| `src/runtime-spec.ts` | `RuntimeReportSpec` grammar, strict parser, limits, canonical JSON, Web Crypto digest (browser-safe) |\n| `src/runtime-spec-hash.ts` | `runtimeReportSpecHash()` (`node:crypto`, server only) |\n| `src/runtime-plan.ts` | Column, operator, aggregate, coercion and cell rules shared by both runners (browser-safe) |\n| `src/runtime-compiler.ts` | `compileRuntimeReportSpec()`, `describeRuntimeReportSource()`, `runRuntimeReport()` |\n| `src/runtime-dimensions.ts` | Time and grouping hints in source descriptions (browser-safe) |\n| `src/runtime-time.ts` | Time language: buckets and periods from words, against `now` (browser-safe) |\n| `src/runtime-memory.ts` | `runRuntimeReportInMemory()`, `describeRuntimeReportMemorySource()` (browser-safe) |\n| `src/spec.ts` | The `./spec` subpath: the browser-safe exports above |\n| `src/runtime-server.ts` | Same-origin confirmation, principal-bound run/archive, chart loader |\n| `src/runtime-report.ts` | `RuntimeReport` model (`runtime_reports`), `saveRuntimeReport()`, list/get/archive, `runStoredRuntimeReport()` |\n\nAssistant tools live in `@happyvertical/smrt-chat` (`createRuntimeReportTools()`,\n`src/runtime-report-tools.ts`).\n\n\nSource definitions may set `fields` (an allow-list) and `excludeFields` (a deny-list).\nBoth use exact public model field names. Omitted `fields` retains all eligible\nfields; `fields: []` exposes none. Exclusions win, and neither option bypasses\nmodel sensitivity, field permissions, or tenant restrictions. Invalid lists and\nunknown names reject the source with `unsupported_source`, including misspelled\nexclusions. Descriptions, assistant tools, confirmation and saved-report runs\nresolve this same policy on every invocation.\n\nStandard timestamps have one public spelling: `createdAt` and `updatedAt`.\nSnake-case `created_at`/`updated_at` remain physical SQL columns, not accepted\nspec or configuration field names. Existing saved specs using those aliases must\nbe proposed again with canonical names and confirmed. Model restrictions on any\nalias protect the whole physical column; host exclusions also cover aliases.\n\n```typescript\n{ id: 'incidents', className: 'Incident', collection: 'incidents',\n fields: ['id', 'title', 'createdAt', 'status'],\n excludeFields: ['signatureAssetId'] }\n```\nThe example assumes `signatureAssetId` is a declared model field; exclusions\nare validated even if an allow-list already omits that field.\n\n## Spec\n\n`version: 1`, `title`, optional `description`, `source` (a server-owned source\nid), `dimensions[]` (`field`, `as?`, `bucket?`), `measures[]` (`fn`: `count`,\n`countDistinct`, `sum`, `avg`, `min`, `max`; `field?`; `as?`), `filters[]`\n(AND-ed; ops `eq ne gt gte lt lte in notIn contains isNull isNotNull`),\n`having[]` (measure alias, numeric compare), `sort[]`, `limit` (1-1000, default\n100) and a `chart` hint (`table|bar|line|pie|stat`, `x`, `y[]`). Unknown keys\nat any level are rejected. Bounds (entries, string length, `in` list size,\nalias charset, reserved words) are in `RUNTIME_REPORT_LIMITS`.\n\nThe parser normalizes defaults and derives aliases, so equal specs hash equally\n(`runtimeReportSpecHash`). The hash is what a human confirmation binds to.\n`runtimeReportSpecDigest` computes the same hex with Web Crypto for browsers\n(async; needs a secure context).\n\n## Browser grammar and in-memory runner (#4100)\n\n`@happyvertical/smrt-reports/spec` imports no Node built-in and, of\nsmrt-core, only the import-free `@happyvertical/smrt-core/smrt-error` (the\nroot entry still reaches the registry's manifest loader), so a browser parses\nspecs with the server's own parser. `runRuntimeReportInMemory(spec,\nrows, { sources, maxRows?, now? })` evaluates a parsed spec over rows the\ncaller already holds and returns the `RuntimeReportResult` shape (`specHash`\nincluded). A `RuntimeReportMemorySource` is `{ id, label?, description?,\nschema: [{ name, type, label?, format? }], fields?, excludeFields? }`: the same\nallow/deny semantics as a server source, `_`-prefixed names and `tenantId`\nnever nameable, and a declared `deletedAt` soft-deletes.\n`describeRuntimeReportMemorySource()` is the `reports.runtime.sources`\ncounterpart.\n\nBoth runners call `runtime-plan.ts` for columns, operator/aggregate rules and\nvalue coercion, so errors carry the same codes and paths. SQL-shaped semantics:\ncomparisons and `IN`/`NOT IN` never match NULL, `contains` is case-sensitive,\ngroups without dimensions always yield one row, NULLs sort first ascending (as\nSQLite), weeks start Monday, buckets are UTC. Result datetimes are ISO-8601\n(PostgreSQL/DuckDB form; SQLite returns bucket TEXT). `runtime-memory-parity.test.ts`\nruns a spec matrix through both runners on SQLite and requires identical results.\n\n### Time and grouping hints\n\nBoth source descriptions carry `timeFields`, `defaultTimeField` (the natural\ndate \"by month\" buckets: an invoice's issue date, never `createdAt` when a\nbusiness date exists) and `dimensions` (fields worth grouping by, most useful\nfirst), and each field a `dimension` kind (`time`, `category`, `relation`) when\nit is one, plus its declared `enum`. A source definition may declare\n`timeField` and `dimensions` (canonical names; unknown names are\n`unsupported_source`, hidden ones are dropped for that principal). Otherwise\n`runtime-dimensions.ts` derives them: a business date\n(`@field({ ui: { format: 'date' } })`) else the first non-bookkeeping datetime;\nclosed text fields, booleans and foreign keys as groupings, never `id`, free\ntext or names marking plumbing (`…Hash`, `…Json`, `…Authority`, `external…`,\n`historical…`). They are hints for choosing, not authority: a spec may still\ngroup by any exposed field.\n\n`parseRuntimeReportTime(text, now)` reads a request's time words (\"by month\",\n\"weekly\", \"over time\", \"last quarter by week\") into a bucket, a period and\nwhether time came up; `resolveRuntimeReportTimeRange(phrase, now)` resolves\n\"last month\", \"this year\", \"last 90 days\", \"Q3\", \"December\" to `[from, to)`\ndates (UTC). Assistants resolve time with these rather than asking a model to\ndo date arithmetic.\n\n**It is a browser preview and test runner, not an authority boundary.** It has\nno registry field policy, principal, RBAC or tenant: whoever supplies the rows\nhas already decided they may be seen. Production reports compile on the server\nfor the live principal and save only through the confirmed `saveRuntimeReport()`.\n\n## Authority model\n\nA spec carries **no authority**. Everything is decided at compile time from\ninputs the caller cannot supply through the spec:\n\n- **Sources.** `RuntimeReportCompileContext.sources` is a server allow-list of\n `{ id, className, collection }`. The spec names an id; unknown and\n not-offered answer identically (`unknown_source`). `authorizeSource` is the\n host's RBAC hook (the chat tools call `run.assertOperation(collection,\n 'read')`) and runs before any field is enumerated. A host should also narrow\n `sources` to those the principal may read before compiling (the chat tools do),\n because `authorizeSource` only runs for an id that is in the list: otherwise\n an RBAC refusal for a configured id and `unknown_source` for an absent one are\n different answers, and a caller can enumerate the configured source ids. `collection` is the\n permission-catalog collection **slug** (the `<collection>` of\n `<collection>.read`, for example `runtimereports`), or the registered model\n class, which resolves to that slug through the catalog's own helper. It is\n never a class name string: `Invoice` derives `Invoice.read`, which no\n catalog contains, so every read is denied and the source is silently not\n offered.\n- **Field policy.** Names are resolved from the ObjectRegistry, never from the\n spec. Not nameable: `sensitive` / `sensitivity: sensitive|secret` fields,\n `readPermission` fields unless `context.permissions` holds that permission,\n `transient`, `json`/relationship fields, `_`-prefixed internals and the tenant\n column. A hidden field is reported exactly like an absent one\n (`unknown_field`), so the compiler is not an existence oracle.\n- **Types.** `sum`/`avg` need numeric fields, `min`/`max` numeric or datetime,\n `bucket` needs datetime, `contains` needs text, id fields accept only UUIDs\n and equality-style ops. Values are coerced to the field type, then bound.\n- **Tenancy.** Raw aggregates bypass collection interceptors, so the compiler\n adds the tenant predicate itself (same column resolution as refresh).\n Tenant-scoped source with no tenant in scope reads only NULL-tenant rows;\n there is no cross-tenant option and `withSystemContext()`/super-admin bypass\n are deliberately not honored. Sources without a tenant column are global by\n definition. `deletedAt` and STI-child discriminators are applied when the\n source has them.\n- **SQL safety.** The plan is an `AggregateSpec` executed by the SDK\n `buildAggregate()`: identifiers are registry-derived and re-validated by the\n builder, values are `$N` parameters, and output aliases are prefixed `r_`\n inside the SQL so an alias can never shadow a source column.\n- **Re-validation.** A stored report is re-parsed (hash-checked) and\n re-compiled against the **running** principal on every run, so policy changes\n apply immediately and a viewer without a permission cannot run a report saved\n by someone who had it.\n- **Stored-report storage.** The tenancy interceptor filters by the AMBIENT\n tenant, while compilation uses the principal's tenant. The chat tools bind the\n two: they enter the principal's tenant context for `list`/`get`/`save` (as the\n data-surface guard does), refuse when an ambient tenant disagrees with the\n principal (on `apply`, before the human is asked to confirm, #3768), require\n a tenant for any stored-report use, and pass the principal\n tenant as an explicit owner filter (`getRuntimeReport`/`listRuntimeReports`\n accept `tenantId`) that still holds under a system context.\n\n`listRuntimeReports` also accepts exact `createdByUserId` and `specHash`\npredicates. They are ANDed with status and explicit/ambient tenant filters before\nlimiting results, so hosts can list a principal's saved reports or find a previous\nsave of the compiled normalized spec without retrieving other authors' reports.\nThese filters never replace authorization. See the\n[list-filter contract and test matrix](runtime-report-list-filters.md).\n\n## Storage and surface\n\n`RuntimeReport` is `@TenantScoped({ mode: 'required' })` with `spec` (normalized\nJSON text), `specHash`, denormalized `title`/`description`/`sourceId`,\n`status` (`active|archived`) and `createdByUserId`. `validateBeforeSave()` parses\nwhatever was written and re-derives every denormalized column, so columns\ncannot disagree with the spec. `getSpec()` throws if the JSON no longer matches\n`specHash` (out-of-band edit). Adopting apps need a `db:migrate` for the new\n`runtime_reports` table; runtime never creates schema. Existing deployments also\nrun `db:migrate` for the confirmation lookup index `idx_runtime_reports_confirm`\nbefore enabling browser confirmation.\n\n**Invariant: no row is inserted, and no spec/title/source/description/author is\nchanged, except through the confirmed save.** It is enforced in the model layer,\nnot by which surfaces exist. `validateBeforeSave()` refuses (`confirmation_required`,\n403) every insert, and every update that changes those columns, unless the\ninstance carries a confirmation proof. The proof is a symbol-keyed constructor\noption plus a module-private `WeakMap`; only `saveRuntimeReport()` can mint it,\nand only when `confirmedSpecHash` equals the compiled plan's hash (the value\nhanded to the application's `RuntimeReportConfirmationHost`). It is single use\nand tied to that exact spec hash. A REST body, a manifest tool call or\n`new RuntimeReport({...}).save()` cannot carry it, so it is refused whatever\nsurface delivered it. A reused id on an insert is refused the same way, so it\ncannot overwrite a stored spec. Archiving or unarchiving (a `status` change with\nthe stored columns untouched) is allowed for an authorised writer.\n\n**Exposed operations** (these decide the permission catalog and RLS grants):\n\n| Surface | Operations |\n| --- | --- |\n| REST (`api`) | `list`, `get`, `create`, `run`, `archive` |\n| CLI | `list`, `get`, `run`, `archive` |\n| MCP | `list`, `get`, `run`, `archive` |\n\nThe permission catalog therefore holds exactly `<collection>.read` and\n`<collection>.create` for `RuntimeReport` (the collection slug is\n`runtimereports`). `update` and `delete` exist on no surface, so they are not in\nthe catalog, not grantable to a role and not nameable in a persona's\n`allowedTools`. REST `create` exists only so the catalog knows the operation the\nconfirmed save performs (`assertOperation(RuntimeReport, 'create')`); its body is\nalways refused by the invariant above. The generic manifest tool dispatcher in\n`@happyvertical/smrt-chat` additionally never offers or runs a write operation on\n`RuntimeReport` (`isRuntimeReportWriteOperation`), so the assistant persists a\nreport only through `reports.runtime.define` (apply).\n\n**Result rows are never persisted.** A result computed for one principal must\nnot be served to another, so the table stores definitions only.\n\n## Why not materialize\n\nDeclared reports materialize into a build-time `@smrt()` table and refresh\nthrough the lock/watermark engine. Runtime schema creation is forbidden here, so\na runtime spec runs as a bounded live aggregate on the same `AggregateSpec`\ncompile target instead. Promoting a proven runtime spec to a declared,\nmaterialized `@report` (codegen plus a migration) is a maintainer decision and\nis tracked as a follow-up.\n\n## Money\n\nMoney fields are integer minor units; `sum`/`min`/`max` keep the integer type and\nthe source field's `format` hint is carried onto the result column. Integer\nresults beyond the JavaScript safe range throw `invalid_result` rather than\nlosing precision. `avg` is decimal.\n\n## Assistant and browser flow (#3878)\n\n`reports.runtime.sources` describes fields available to the assistant principal.\n`reports.runtime.define` with `phase: 'preview'` compiles and runs a bounded\nsample. `phase: 'apply'` requires the preview's exact normalized `specHash`.\nWithout an in-process confirmation host it returns:\n\n```ts\n{ status: 'awaiting_confirmation', specHash, spec, sourceLabel, preview,\n confirmPath: '/api/_reports/runtime/confirm' }\n```\n\nNothing is saved by that response, and model-supplied consent is ignored. The\nbrowser shows the proposal and only a person's approval posts `{ spec, specHash }`\nto `createRuntimeReportConfirmHandler()`. The handler checks same origin, the\nverified session user and tenant, `runtimereports.create`, the normalized hash,\nand compilation under the **confirming** principal's current permissions.\nAnother principal may approve the same public spec only under their own\npermissions and tenant; a hash is data, not a transferable authorization token.\n\nThe template mounts `POST /api/_reports/runtime/confirm`. Hosts pass the verified\nprincipal and the request's database (including the RLS transaction), never\nbody-supplied identity. Success is `201 { id, specHash, title }`; a retry of an\nactive definition with the same principal/hash returns the same response with\n200. Compilation happens again even on retries. Concurrent approvals use core's\ntransactional `runOnce` claim, keyed by tenant, principal and normalized spec.\nA failed write rolls back the claim; an audit\ncallback failure returns a generic 500 and a retry finds the already saved row.\nNo result rows are stored in the idempotency record. After archiving, approving\nthe same definition returns 409 `report_archived`; restore it through the archive\naction before retrying.\n\nErrors are JSON `{ code, message }`: 401 without a session; 403 for cross-origin,\nmissing permission, mismatched ambient tenant, or an active retry invalidated by\ncurrent source/field access; 409 for an archived retry; 422 for a malformed new\nspec or `spec_hash_mismatch`; generic 500 for unexpected provider failures. There is\nno cross-tenant or system bypass. Configure an optional `audit` callback on the\nfactory to receive confirmed principal/hash/report identity and whether reused.\n\nFor CLI and other in-process hosts, `RuntimeReportConfirmationHost.confirmSave()`\nremains available: it must resolve only after a person approves that exact hash.\nThe single-use model proof is unchanged in both paths. The assistant tools use\nthe persona's fail-closed `allowedTools` gates.\n\n## Server configuration and actions\n\nConfigure `packages.reports.runtime.sources` in `smrt.config.ts`:\n\n```ts\npackages: {\n reports: { runtime: { sources: [\n { id: 'invoices', className: '@acme/app:Invoice', collection: 'invoices', label: 'Invoices' }\n ] } }\n}\n```\n\nAn absent source list exposes nothing. A source's `collection` is a catalog slug\nand requires `<collection>.read`; the server narrows the allow-list before\ncompiling. Give the assistant the same server-owned source definitions. The\nconfirm factory can instead take explicit `{ sources, audit? }` options.\n\n`POST /api/runtimereports/:id/run` takes no body and returns\n`{ action: 'run', result: RuntimeReportResult }`. Its CLI/MCP counterparts call\nthe same model action. It requires `runtimereports.read`, reloads the definition\nin the principal's tenant, and recompiles on every call. Tenant peers can run\nshared reports; use `createdByUserId` for an Only mine list filter. Missing and\nforeign-tenant ids return 404; revoked source/field access returns 403; archived\nreports return 409 `report_archived`; invalid results return 422. Rows stay\nephemeral and integer money stays in minor units.\n\n`POST /api/runtimereports/:id/archive` takes `{ archived: boolean }` and returns\n`{ action: 'archive', result: { id, status } }`. It requires\n`runtimereports.create`, changes status only, and\nrepeating the same state does not write again. `operationPermissions` metadata\naliases run to read and archive to create consistently across generated routes,\nCLI/MCP guards and the permission catalog. The archive alias adds SELECT and\nUPDATE SQL-policy bindings to create: the authorized action must look up the\nsame-tenant row before changing its status. Adopted PostgreSQL RLS policies must\nbe regenerated. Neither `.run`, `.archive`, `.update` nor `.delete` becomes a\nnew grantable permission for this model.\n\n`loadRuntimeReportChart(options, context)` is the server loader for the dependent\nbrowser recipe widget. Options are `{ reportId, measure, dimension? }`; the host\nsupplies `context.reportPrincipal` from its authenticated request and optionally\n`currency`. It runs afresh as the viewer and returns structural chart data:\n`{ points: [{label, value}], format, currency?, href }`. The loader has no\nsmrt-svelte dependency and receives no authority from widget options.\n\n## Recipe UI\n\n`reports.runtime` declares the RuntimeReport model, Reports navigation, the\n`/reports` routes and `runtime-report-chart` widget. The widget options are only\n`{ reportId, measure, dimension? }`; the authenticated server host supplies the\nloader's `reportPrincipal`. Static hosts render the Reports route unavailable.\nRename, scheduling and manual report construction remain deferred.\n"
|
|
1276
1277
|
},
|
|
1277
1278
|
{
|
|
1278
1279
|
"path": "README.md",
|
|
@@ -1342,17 +1343,41 @@
|
|
|
1342
1343
|
],
|
|
1343
1344
|
"nav": [
|
|
1344
1345
|
{
|
|
1345
|
-
"label": "
|
|
1346
|
+
"label": "Saved reports",
|
|
1346
1347
|
"model": "@happyvertical/smrt-reports:RuntimeReport",
|
|
1347
|
-
"icon": "fileText"
|
|
1348
|
+
"icon": "fileText",
|
|
1349
|
+
"description": "Reports your team approved, kept up to date.",
|
|
1350
|
+
"noun": "report"
|
|
1348
1351
|
}
|
|
1349
1352
|
],
|
|
1350
1353
|
"requires": [],
|
|
1351
1354
|
"help": {
|
|
1352
|
-
"markdown": "# Reports\n\nAsk the assistant for a total, comparison, or trend. Review the proposed report\nand approve it to save it. Your saved reports are shared with your team; each\nperson sees results using their own access to the underlying information.\n\nReports run fresh when opened. You can archive a report to hide it from the\nactive list and restore it later. Creating and restoring reports needs report\nwriting access. Reports need a connected server
|
|
1355
|
+
"markdown": "# Reports\n\nAsk the assistant for a total, comparison, or trend. Review the proposed report\nand approve it to save it. Your saved reports are shared with your team; each\nperson sees results using their own access to the underlying information.\n\nReports run fresh when opened. You can archive a report to hide it from the\nactive list and restore it later. Creating and restoring reports needs report\nwriting access. Reports need a connected server; the smrt planner previews them over its\nsample records instead. Scheduling, renaming, and exporting reports are not available yet.\n",
|
|
1353
1356
|
"fieldRefs": []
|
|
1354
1357
|
},
|
|
1355
1358
|
"surfaces": [
|
|
1359
|
+
{
|
|
1360
|
+
"kind": "widget",
|
|
1361
|
+
"type": "saved-reports",
|
|
1362
|
+
"export": "@happyvertical/smrt-reports/svelte#SavedReportsWidget",
|
|
1363
|
+
"label": "Saved reports",
|
|
1364
|
+
"description": "Your team’s saved reports with their latest figures.",
|
|
1365
|
+
"icon": "fileText",
|
|
1366
|
+
"options": [
|
|
1367
|
+
{
|
|
1368
|
+
"key": "limit",
|
|
1369
|
+
"type": "integer",
|
|
1370
|
+
"label": "Reports shown",
|
|
1371
|
+
"default": 6,
|
|
1372
|
+
"min": 1,
|
|
1373
|
+
"max": 24
|
|
1374
|
+
}
|
|
1375
|
+
],
|
|
1376
|
+
"sectionDefault": true,
|
|
1377
|
+
"defaultSpan": 4,
|
|
1378
|
+
"minSpan": 2,
|
|
1379
|
+
"maxSpan": 4
|
|
1380
|
+
},
|
|
1356
1381
|
{
|
|
1357
1382
|
"kind": "route",
|
|
1358
1383
|
"path": "/reports",
|
package/dist/spec.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@happyvertical/smrt-reports/spec`: the browser-safe runtime report surface
|
|
3
|
+
* (#4100).
|
|
4
|
+
*
|
|
5
|
+
* The closed `RuntimeReportSpec` grammar and its parser import no Node
|
|
6
|
+
* built-in, so a browser (the planner's assistant, a static host) validates a
|
|
7
|
+
* spec with the same code the server compiles. The server-only pieces stay on
|
|
8
|
+
* the package root: `runtimeReportSpecHash` (`node:crypto`),
|
|
9
|
+
* `compileRuntimeReportSpec` / `runRuntimeReport` (ObjectRegistry and SQL) and
|
|
10
|
+
* the `RuntimeReport` model. `src/__tests__/spec-entry.test.ts` fails when
|
|
11
|
+
* this entry's import graph reaches a Node built-in.
|
|
12
|
+
*
|
|
13
|
+
* `runRuntimeReportInMemory()` evaluates a spec over rows the caller holds,
|
|
14
|
+
* returning the `runRuntimeReport()` result shape. It is a browser preview
|
|
15
|
+
* and test runner, not an authority boundary: server compilation and RBAC
|
|
16
|
+
* still own production reports.
|
|
17
|
+
*/
|
|
18
|
+
export type { RunRuntimeReportInMemoryOptions, RuntimeReportMemoryField, RuntimeReportMemoryRow, RuntimeReportMemorySource, } from './runtime-memory.js';
|
|
19
|
+
export { describeRuntimeReportMemorySource, runRuntimeReportInMemory, } from './runtime-memory.js';
|
|
20
|
+
export type { RuntimeReportColumn, RuntimeReportColumnType, RuntimeReportDimensionHints, RuntimeReportDimensionKind, RuntimeReportResult, RuntimeReportSourceDescription, } from './runtime-plan.js';
|
|
21
|
+
export type { RuntimeReportBucket, RuntimeReportChart, RuntimeReportChartType, RuntimeReportDimension, RuntimeReportErrorCode, RuntimeReportFilter, RuntimeReportFilterOp, RuntimeReportHaving, RuntimeReportHavingOp, RuntimeReportMeasure, RuntimeReportMeasureFn, RuntimeReportScalar, RuntimeReportSort, RuntimeReportSpec, } from './runtime-spec.js';
|
|
22
|
+
export { parseRuntimeReportSpec, RUNTIME_REPORT_BUCKETS, RUNTIME_REPORT_CHART_TYPES, RUNTIME_REPORT_FILTER_OPS, RUNTIME_REPORT_HAVING_OPS, RUNTIME_REPORT_LIMITS, RUNTIME_REPORT_MEASURE_FNS, RUNTIME_REPORT_SPEC_VERSION, RuntimeReportError, runtimeReportSpecDigest, serializeRuntimeReportSpec, } from './runtime-spec.js';
|
|
23
|
+
export type { RuntimeReportTimeIntent, RuntimeReportTimeRange, } from './runtime-time.js';
|
|
24
|
+
export { parseRuntimeReportTime, resolveRuntimeReportTimeRange, runtimeReportBucketForSpan, } from './runtime-time.js';
|
|
25
|
+
//# sourceMappingURL=spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../src/spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,YAAY,EACV,+BAA+B,EAC/B,wBAAwB,EACxB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,iCAAiC,EACjC,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,mBAAmB,EACnB,uBAAuB,EACvB,2BAA2B,EAC3B,0BAA0B,EAC1B,mBAAmB,EACnB,8BAA8B,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,qBAAqB,EACrB,0BAA0B,EAC1B,2BAA2B,EAC3B,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC"}
|
package/dist/spec.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { C as runtimeReportSpecDigest, S as parseRuntimeReportSpec, _ as RUNTIME_REPORT_HAVING_OPS, a as runRuntimeReportInMemory, b as RUNTIME_REPORT_SPEC_VERSION, g as RUNTIME_REPORT_FILTER_OPS, h as RUNTIME_REPORT_CHART_TYPES, i as describeRuntimeReportMemorySource, m as RUNTIME_REPORT_BUCKETS, n as resolveRuntimeReportTimeRange, r as runtimeReportBucketForSpan, t as parseRuntimeReportTime, v as RUNTIME_REPORT_LIMITS, w as serializeRuntimeReportSpec, x as RuntimeReportError, y as RUNTIME_REPORT_MEASURE_FNS } from "./chunks/runtime-time-D7JZ1e4J.js";
|
|
2
|
+
export { RUNTIME_REPORT_BUCKETS, RUNTIME_REPORT_CHART_TYPES, RUNTIME_REPORT_FILTER_OPS, RUNTIME_REPORT_HAVING_OPS, RUNTIME_REPORT_LIMITS, RUNTIME_REPORT_MEASURE_FNS, RUNTIME_REPORT_SPEC_VERSION, RuntimeReportError, describeRuntimeReportMemorySource, parseRuntimeReportSpec, parseRuntimeReportTime, resolveRuntimeReportTimeRange, runRuntimeReportInMemory, runtimeReportBucketForSpan, runtimeReportSpecDigest, serializeRuntimeReportSpec };
|