@happyvertical/smrt-reports 0.57.31 → 0.57.33
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 +1 -0
- package/README.md +64 -3
- package/dist/adapter.d.ts +18 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/chunks/compiler-IUB2YNgM.js +341 -0
- package/dist/chunks/compiler-IUB2YNgM.js.map +1 -0
- package/dist/compiler.d.ts +2 -0
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +2 -171
- package/dist/decorators.d.ts +22 -22
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +16 -8
- package/dist/decorators.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -20
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/refresh.d.ts +0 -1
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +6 -18
- package/dist/refresh.js.map +1 -1
- package/dist/registry-columns.d.ts +14 -0
- package/dist/registry-columns.d.ts.map +1 -0
- package/dist/runtime-compiler.d.ts.map +1 -1
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +2 -2
- package/dist/scheduler.js.map +1 -1
- package/dist/smrt-knowledge.json +7 -7
- package/dist/state.js +1 -1
- package/dist/state.js.map +1 -1
- package/dist/types.d.ts +64 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/views.d.ts.map +1 -1
- package/package.json +9 -9
- package/dist/compiler.js.map +0 -1
package/dist/smrt-knowledge.json
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
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.33",
|
|
7
7
|
"sourceManifestPath": "dist/manifest.json",
|
|
8
8
|
"agentDocPath": "AGENTS.md",
|
|
9
9
|
"sourceHashes": {
|
|
10
|
-
"manifest": "
|
|
11
|
-
"packageJson": "
|
|
12
|
-
"agents": "
|
|
10
|
+
"manifest": "ab243e5c6ed1f7474577ad78436c3a6b8207051514ff51da00b40b02465894bb",
|
|
11
|
+
"packageJson": "6a0b632ee9659c31ca20ae001808b2e48c0f3e9ddb4e327fff17181c77bcce1b",
|
|
12
|
+
"agents": "f1e1c9b47ac380d83484381073c4e4c05e86546a66ddc7ef1bb72e048795dd3b",
|
|
13
13
|
"moduleDoc:agents/runtime-report-browser.md": "4b7d8d3d3766e7ff0ae07b5c78e23a66d2be9dd2f7a3da2dfdc2330bcc9e1516",
|
|
14
14
|
"moduleDoc:agents/runtime-reports.md": "6afffd734071fbe953cc07db6dca205dbc17eba320a98408026dc96aaf825a39",
|
|
15
|
-
"moduleDoc:README.md": "
|
|
15
|
+
"moduleDoc:README.md": "41af6d50b3e85275efabce19c9aaf3100b837ac014d64c252febd1285b0263df"
|
|
16
16
|
},
|
|
17
17
|
"exports": [
|
|
18
18
|
".",
|
|
@@ -1263,7 +1263,7 @@
|
|
|
1263
1263
|
"polymorphicAssociations": 0,
|
|
1264
1264
|
"uuidColumns": 24
|
|
1265
1265
|
},
|
|
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
|
+
"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- Joins, row expressions and filtered measures (#3903) compile to the SDK's `AggregateSpec` (`fromAlias`, `joins`, `expr`, `filter`); expressions are literal data nodes because the scanner reads decorator arguments statically. Qualify every source column with `src` once a report joins (refresh filters do), put the tenant match in the join's `ON`, and joined reports rebuild (an incremental request is run as a rebuild), and drilldown refuses joined or computed group keys.\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",
|
|
1267
1267
|
"moduleDocs": [
|
|
1268
1268
|
{
|
|
1269
1269
|
"path": "agents/runtime-report-browser.md",
|
|
@@ -1278,7 +1278,7 @@
|
|
|
1278
1278
|
{
|
|
1279
1279
|
"path": "README.md",
|
|
1280
1280
|
"module": "README",
|
|
1281
|
-
"content": "# @happyvertical/smrt-reports\n\nMaterialized aggregate reports for s-m-r-t. Define a report as a decorated class,\ncompile it to a portable aggregate query, and refresh its normal s-m-r-t table\nmanually, on a schedule, after source changes, or when a TTL expires.\n\nRuntime refresh checks that its tables exist (existence only, not columns or\nindexes) and fails clearly if they do not; it does not create report or system\ntables. Include report models in normal manifest-driven migrations before\nrefreshing.\n\n## Installation\n\n```bash\npnpm add @happyvertical/smrt-reports\n```\n\n## Define a report\n\n```ts\nimport { SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport {\n groupBy,\n month,\n report,\n SmrtReport,\n SmrtReportCollection,\n sum,\n} from '@happyvertical/smrt-reports';\n\n@smrt()\nclass Invoice extends SmrtObject {\n customerId = '';\n issuedAt = new Date();\n subtotal = 0.0;\n status = '';\n}\n\n@report({\n source: Invoice,\n where: { status: 'paid' },\n refresh: { manual: true },\n})\n@smrt()\nclass MonthlyRevenue extends SmrtReport {\n @groupBy('customerId') customerId = '';\n @month('issuedAt') issuedMonth = new Date();\n @sum('subtotal') revenue = 0.0;\n}\n\nclass MonthlyRevenueCollection extends SmrtReportCollection<MonthlyRevenue> {\n static readonly _itemClass = MonthlyRevenue;\n}\n\nconst reports = await MonthlyRevenueCollection.create({ db: 'app.db' });\nawait reports.refresh();\nconst rows = await reports.list({ orderBy: 'issued_month DESC' });\n```\n\n## Decorators\n\n| Decorator | Meaning |\n| --- | --- |\n| `@report({ source, ... })` | Declare the source and refresh policy |\n| `@groupBy(column?)` | Group by a source column |\n| `@minute()` through `@year()` | Bucket a source timestamp |\n| `@sum()`, `@avg()`, `@min()`, `@max()` | Aggregate a source column |\n| `@count()` | Count rows or distinct values |\n| `@aggregate()` | Define a custom supported aggregate shape |\n\nEvery non-system report field must be a grouping key, time bucket, or aggregate.\nMetadata is stored under the field's `_meta.__report` contract so scanner and\nruntime compilation stay aligned.\n\n## Refresh modes\n\n- `rebuild` replaces the materialized result.\n- `incremental` recomputes groups affected after a source watermark and removes\n groups that become empty.\n- TTL-backed collections refresh before reads when the report is stale.\n- `ReportScheduleRunner` and `registerReportRefreshInterceptor()` enqueue\n durable refresh jobs through [`smrt-jobs`](../jobs/README.md).\n\nIncremental sources need watermark and soft-delete columns, normally\n`updatedAt` and `deletedAt`. Tenant-scoped aggregate SQL explicitly filters\n`tenant_id`; normal collection interceptors cannot secure a raw aggregate.\n\n## Public entry points\n\nThe package exposes focused subpaths for consumers that want only the compiler,\ndecorators, refresh engine, scheduler, state models, or aggregate compatibility\nhelpers:\n\n```text\n@happyvertical/smrt-reports\n@happyvertical/smrt-reports/compiler\n@happyvertical/smrt-reports/decorators\n@happyvertical/smrt-reports/refresh\n@happyvertical/smrt-reports/scheduler\n@happyvertical/smrt-reports/state\n@happyvertical/smrt-reports/aggregate\n```\n\n## Report adapter\n\nThe package also exports a transport-neutral adapter for report surfaces:\n\n```ts\nimport {\n buildReportAdapterDescriptor,\n buildReportDrilldownQuery,\n queryReportMaterializedRows,\n reportMaterializedRowKey,\n splitReportFilterScopes,\n} from '@happyvertical/smrt-reports';\n\nconst descriptor = await buildReportAdapterDescriptor(MonthlyRevenue, {\n tenantScope: 'current',\n});\nconst reports = await MonthlyRevenueCollection.create({ db: 'app.db' });\nconst result = await queryReportMaterializedRows(\n MonthlyRevenue,\n {\n version: 1,\n requestId: 'monthly-revenue-first-page',\n mode: 'rows',\n projection: ['id', 'customer_id', 'revenue'],\n filter: {\n kind: 'all',\n filters: [\n {\n kind: 'condition',\n field: 'customer_id',\n operator: 'eq',\n value: 'customer-42',\n },\n {\n kind: 'condition',\n field: 'revenue',\n operator: 'gte',\n value: 1000,\n },\n ],\n },\n page: { kind: 'offset', offset: 0, limit: 25 },\n sort: [{ field: 'revenue', direction: 'desc' }],\n },\n {\n collection: reports,\n // Preserve the resource identity of the descriptor selected above.\n adapter: { tenantScope: 'current' },\n },\n);\nconst rowKey = reportMaterializedRowKey(result.rows[0]);\nconst drilldown = await buildReportDrilldownQuery(MonthlyRevenue, result.rows[0]);\n```\n\n`ReportAdapterDescriptor` is deterministic JSON with a stable resource id,\n`id` as the identity field, typed report columns, a canonical `DataQuerySchema`,\nand structural DataTable hints. The hints are deliberately not a `smrt-ui`\ndependency. Consumers may map the descriptor to their own presentation layer.\nThe adapter exposes only persisted report columns and the primary key: transient,\nsystem, and non-column fields are not surfaced. Sensitive/secret fields and\nfields with a `readPermission` are excluded without a principal, so the\ndescriptor fails closed.\n\nThe `dataTable.columns` entries carry neutral `headerPath`, `valueFormat`,\nalignment, role, and responsive hints. Grouping fields, time buckets, and\naggregate measures receive deterministic multi-level header ancestry; a\nconsumer can override any column by stable id with\n`buildReportAdapterDescriptor(..., { dataTable: { columns: { ... } } })`.\n`valueFormat` is an instruction for the rendering boundary only: rows returned\nby `queryReportMaterializedRows()` retain their raw JSON-safe values for\nsorting, exports, and agents. Use `dataTable.structuralRows` for a computed\nsummary, subtotal, aggregate, or footer. Each is marked `selection: 'excluded'`\nand `actions: 'excluded'`, and must be passed to the consumer table's structural\nrow surface rather than its selectable data rows.\n\n`queryReportMaterializedRows()` is the bounded read slice for already-materialized\nrows. It supports projection, offset/limit paging (default limit 50),\ndeterministic multi-sort (with `id` as the final tie-break), typed filters, and\ndatabase-backed dimension facets. A descriptor marks group/time fields as\n`filterScope: 'where'` and aggregate measures as `filterScope: 'having'`; use\n`splitReportFilterScopes()` when constructing a live source query. An AND may\ncombine the two scopes, but an OR or NOT cannot mix them, because moving either\nside across a source `WHERE`/`HAVING` boundary would change its meaning.\n\nMaterialized query results normalize hydrated values against their declared\ncolumn types. Objects in scalar columns become JSON text; JSON columns retain\nstructured values. Date-only and timezone-less timestamps use UTC, matching\nSQLite storage, and temporal facet buckets follow the same rule. Strings over\n4096 characters are shortened with `truncated` and a warning, except row IDs:\nidentities are never rewritten, and unsupported IDs fail validation. Unsafe bigint\nvalues fail instead of silently losing precision.\n\nThe materialized collection executes the normalized, allowlisted predicate as\nparameterized SQL and applies it identically to rows, totals, and facets. It\nnever accepts raw SQL, source field paths, tenant ids, or principal ids.\nThe descriptor's `queryExecution` contract declares three delivery choices:\n`visible` (the default) returns rows for an already-authorized surface,\n`silent` returns the same bounded result while making no visible-surface change,\nand `background` delegates a normalized, authority-free task to the application's\n`enqueueBackgroundQuery` host. A background result is only a queue handle, never\nmaterialized rows. The host retains the authenticated principal, tenant, report\ndefinition, field policy, database, and eventual job execution; none can be\nsupplied in a query request or background task.\nWhen a consumer selects a descriptor with `ReportAdapterOptions`, pass those\nsame options through the query's `adapter` option so returned and background\ntask resource ids stay aligned with the selected descriptor.\n`buildReportDrilldownQuery()` carries only the row's declared groups/buckets\nand a fixed inheritance contract for the current principal, tenant, report\ndefinition, and field policy; an authenticated source adapter must enforce that\ncontract before it reads source records. Time buckets remain declarative so the\nsource adapter keeps the report's database/timezone semantics. Every returned\nrow must have a non-empty string `id`; use that value, never a display or page\nindex, for row identity.\n\nWhen no collection is injected, reads resolve the registered report collection\nthrough `ObjectRegistry`, allowing normal s-m-r-t collection interceptors to enforce\ntenant filtering. `tenantScoped` and `tenantField` in the descriptor are true\nonly when the report is actually registered with tenant metadata; a scope string\nalone is not an authority boundary. An injected collection is application-owned\nand must provide the equivalent tenant boundary. Raw aggregate refreshes still\nneed explicit tenant predicates as described above.\n\nThe descriptor's `refresh` section declares mode, triggers, stale-read behavior,\nand a permissioned, audited `refresh` action with `preview` and `apply` phases.\nThe adapter itself stays read-only. Call `getReportLifecycle()` for a tenant-safe\nsnapshot of current, stale, refreshing, lock-skipped, or failed materialization\nstate; it redacts lock owners, raw errors, and tenant-fanout identifiers. Pass a\n`lifecycle` option to `queryReportMaterializedRows()` only when a consumer needs\nthat context; the result then distinguishes a current, stale, or read-triggered\nrefresh. `previewReportRefresh()` and `applyReportRefresh()` require an\napplication action host to authorize and audit the caller before a durable\nreport-refresh job is queued. Manual refresh hosts must also return a versioned,\nnon-secret `executionAuthority` binding. Each worker process registers the named\nhost with `registerReportRefreshExecutionAuthorityHost()`; the task checks the\npersisted tenant binding, resolves current membership and permission, and records\nan allowed or denied execution audit immediately before refresh. Every enqueue\npath also receives a `DurableJobPayloadSigner`, and every worker registers it\nwith `registerReportRefreshJobIntegritySigner()`. This authenticates the task\ntarget, trigger, tenant scope, authority reference, and payload across storage;\nthe signing key is never persisted. Scheduled and on-change maintenance jobs\nremain system-authority jobs and do not carry an initiating user, but their job\npayloads use the same integrity boundary. Only a registered `SmrtReportCollection` can\nsynchronously refresh a stale read, and only when its TTL policy is positive and\nnot manual.\n\n### Scheduled refresh lifecycle\n\nDeclare `refresh: { schedule: '*/5 * * * *', tenantFanout: 'discover' }`\non a tenant-scoped report to discover distinct non-null source tenants each\nscheduled run. Include scopes still present in the materialized table so a\nthe next rebuild removes stale groups for tenants losing their final source row.\nDiscovery preserves the configured refresh mode. Incremental reports still need\na `fullRebuildSchedule` to catch hard deletions that do not advance a source\nwatermark. Provision schedules with `ensureReportRefreshSchedules({ db,\nreports })`; no discovered scopes means no work, and discovery never refreshes\nthe global slice.\nThe worker uses the registered source/report tenant columns and its supplied\nmaintenance executor. Discovery does not grant database privileges or widen a\ntenant-bound or manual job. Keep `tenantFanout: true` with explicit `tenantIds`\nwhen the host owns a fixed tenant list.\n\nInitialize a `ReportScheduleRunner` and a jobs `TaskRunner` against the migrated\ndatabase, then call `const unbind = schedules.bindTaskRunner(tasks)` before\nstarting them. This connects terminal job events to schedule counters, freeing\nthe concurrency slot after success or failure. Repeated binding is idempotent;\ncall `unbind()` on shutdown. Listen for `runner:error` to detect failed counter\nupdates. Persisted failure messages use the jobs package redaction policy.\nDurable payload signing and execution-time authority checks remain\nrequired; completion accounting uses the signed schedule identity.\n\nRepeated schedule provisioning inserts missing identities and preserves existing\nhistory, next-run time, running count, and operator settings. A different cron,\nmode, or tenant scope identifies a different schedule; explicitly disable obsolete\nschedules when changing those settings.\n\n### Saved views and snapshot exports\n\n`normalizeReportSavedView()` and `restoreReportSavedView()` provide the\nserializable view boundary. A storage host owns the saved view's tenant and\nowner; on every restore it must pass the stored payload through the current\ndescriptor. That reapplies field, projection, sorting, grouping, and definition\npolicy, so a stale view cannot reveal a field that is no longer allowed.\n`migrateReportSavedView()` upgrades the original unversioned (or explicit v0)\nlayout to v1 before that current-policy validation; unsupported future versions\nfail clearly rather than being guessed.\n\nBuild an export from a completed materialized-row read with\n`createReportExportSnapshot()`, supplying an opaque binding from the\napplication's immutable materialization-snapshot host, then call\n`createReportExportRequest()`. The snapshot fixes the canonical query\nfingerprint, normalized projection and sort, exact row count, `asOf`,\n`refreshedAt`, stale state, and definition fingerprint. Every request also\ncontains a deterministic offset-page read plan; a renderer begins at offset zero\nand advances by its validated page size until the exact bounded row count is\nreached. Use `createReportExportPageRequest()` for each page; it preserves the\nfrozen query semantics while replacing only visible pagination.\n\nEvery request is bounded by rows, bytes, and deadline; exports over the\nforeground row limit become an authority-free background handoff. Use\n`previewReportExport()` and `applyReportExport()` with the same application\naction host for human and agent callers. The host authorizes and audits the\nfixed `reports.export` action; exports containing personal, sensitive, or secret\ncolumns require explicit confirmation.\n\nPreview, apply, and every worker call `validateReportExportExecution()`, which\nrequires the host to prove that the opaque binding still resolves to the exact\nimmutable materialization snapshot under its current principal, tenant, report\ndefinition, and field policy. If it cannot, the operation fails rather than\nrelabelling newer rows with an old `asOf`. Artifact metadata has no URL or\ndownload token; before serving it, call `validateReportExportArtifact()` to\nreject expiry, definition drift, and out-of-bounds progress, then apply the\nhost's current authorization and snapshot validation again.\n\n## Runtime reports\n\nA report can also be defined at runtime as data. `RuntimeReportSpec` is a closed,\nversioned structure (source id, dimensions, measures, filters, having, sort,\nchart hint) with no free-form query text. `compileRuntimeReportSpec()` checks it\nagainst a server-owned source allow-list, field policy (sensitive and\npermission-gated fields are not nameable), the caller's permissions, and tenant\nisolation, then targets the same aggregate plan as declared reports.\n`RuntimeReport` stores validated specs per tenant, and a stored spec is\nre-compiled for the running user on every run. Result rows are not stored. A row\ncan only be inserted, or have its spec changed, through `saveRuntimeReport()`\nwith the spec hash a human confirmed; the model layer refuses every other write. The\nchat package offers matching assistant tools that propose a spec, preview it,\nand save only after a human confirms. See\n[`agents/runtime-reports.md`](./agents/runtime-reports.md).\n\n## Browser components\n\n`@happyvertical/smrt-reports/svelte` exports saved-report and detail screens,\na confirmation card, a report/measure picker, and a shared-chart result view.\nThey accept a principal-scoped browser transport and show an unavailable state\nwhen no server is supplied. See the [browser integration contract](./agents/runtime-report-browser.md)\nfor route-host identity and capability props, confirmation wiring, recipe\nsurfaces, and playground previews.\n\n## Development\n\n```bash\npnpm --filter @happyvertical/smrt-reports test\npnpm --filter @happyvertical/smrt-reports typecheck\npnpm --filter @happyvertical/smrt-reports build\n```\n\nSee [`AGENTS.md`](./AGENTS.md) for refresh, schema, and tenancy invariants.\n"
|
|
1281
|
+
"content": "# @happyvertical/smrt-reports\n\nMaterialized aggregate reports for s-m-r-t. Define a report as a decorated class,\ncompile it to a portable aggregate query, and refresh its normal s-m-r-t table\nmanually, on a schedule, after source changes, or when a TTL expires.\n\nRuntime refresh checks that its tables exist (existence only, not columns or\nindexes) and fails clearly if they do not; it does not create report or system\ntables. Include report models in normal manifest-driven migrations before\nrefreshing.\n\n## Installation\n\n```bash\npnpm add @happyvertical/smrt-reports\n```\n\n## Define a report\n\n```ts\nimport { SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport {\n groupBy,\n month,\n report,\n SmrtReport,\n SmrtReportCollection,\n sum,\n} from '@happyvertical/smrt-reports';\n\n@smrt()\nclass Invoice extends SmrtObject {\n customerId = '';\n issuedAt = new Date();\n subtotal = 0.0;\n status = '';\n}\n\n@report({\n source: Invoice,\n where: { status: 'paid' },\n refresh: { manual: true },\n})\n@smrt()\nclass MonthlyRevenue extends SmrtReport {\n @groupBy('customerId') customerId = '';\n @month('issuedAt') issuedMonth = new Date();\n @sum('subtotal') revenue = 0.0;\n}\n\nclass MonthlyRevenueCollection extends SmrtReportCollection<MonthlyRevenue> {\n static readonly _itemClass = MonthlyRevenue;\n}\n\nconst reports = await MonthlyRevenueCollection.create({ db: 'app.db' });\nawait reports.refresh();\nconst rows = await reports.list({ orderBy: 'issued_month DESC' });\n```\n\n## Decorators\n\n| Decorator | Meaning |\n| --- | --- |\n| `@report({ source, ... })` | Declare the source and refresh policy |\n| `@groupBy(column?)` | Group by a source column, a joined column (`'wo.title'`), or `{ expr }` |\n| `@minute()` through `@year()` | Bucket a source timestamp |\n| `@sum()`, `@avg()`, `@min()`, `@max()` | Aggregate a source or joined column, or a row `{ expr }`, optionally `{ filter }`ed |\n| `@count()` | Count rows or distinct values, optionally `{ filter }`ed |\n| `@aggregate()` | Define a custom supported aggregate shape |\n\nEvery non-system report field must be a grouping key, time bucket, or aggregate.\nMetadata is stored under the field's `_meta.__report` contract so scanner and\nruntime compilation stay aligned.\n\n## Joins, row expressions and filtered measures\n\nA report can read a related model, compute a value from each row, and count\nonly the rows a condition holds for. Each compiles to the SQL aggregate API in\n`@happyvertical/sql`; nothing is built as SQL text here.\n\n```ts\n@report({\n source: AttendanceSegment,\n // Many-to-one: AttendanceSegment.workRefId holds a WorkOrder id.\n joins: { wo: { source: WorkOrder, on: 'workRefId' } },\n})\nclass LabourByWorkOrder extends SmrtReport {\n @groupBy() workRefId = '';\n @groupBy('wo.title') workOrder = '';\n @max('wo.estimatedHours') estimatedHours = 0;\n\n // A row expression: seconds from createdAt to claimedAt, averaged.\n @avg({ expr: { op: 'secondsBetween', later: { col: 'claimedAt' }, earlier: { col: 'createdAt' } } })\n avgResponseSeconds = 0;\n\n // A filtered count: one number rather than a two-row grouping.\n @count({ filter: { op: 'eq', left: { col: 'halted' }, right: { value: true } } })\n haltedSegments = 0;\n}\n```\n\n- **Joins** are many-to-one, keyed `alias: { source, on, to?, type? }`. `on` is a\n field of the report source; `to` is the related field it points at (default\n `id`) and must identify one related row per tenant, or source rows repeat.\n `type` is `left` (default, keeps a source row whose related row is gone) or\n `inner`. Aliases are lower-case identifiers and not `src`. Reference a joined\n field as `alias.field` in `@groupBy`, the aggregate and bucket decorators,\n expressions and `where`.\n- **Tenancy is built into the join.** When the related model is tenant-scoped the\n join also matches `tenant_id` between the two rows, so an id that points at\n another tenant's row never matches. A tenant-scoped join from a source with no\n tenant field is refused. Soft-deleted related rows never match.\n- **Field policy follows the data.** A report column that reads a joined field\n marked sensitive or `readPermission`-gated is withheld from the adapter\n descriptor exactly as that field would be.\n- **Expressions are data, written as literals** (the manifest scanner reads\n decorator arguments statically, so builder calls would be dropped): `{ col }`,\n `{ value }`, `add`/`sub`/`mul`/`div`, `secondsBetween`, `eq`/`ne`/`lt`/`lte`/\n `gt`/`gte`, `and`/`or`/`not`, `isNull`/`isNotNull` and `coalesce`. A `col`\n names a model field, never a SQL column. `div` returns NULL for a zero\n divisor. `expr` and `filter` work with `count`, `sum`, `avg`, `min` and `max`.\n- **Joined reports refresh by rebuild only.** A change to a joined row does not\n move the source's watermark, so declaring `mode: 'incremental'` is refused and\n any trigger that asks for an incremental refresh (a schedule, `onChange`, a\n job) is run as a rebuild. List the joined models in `refresh.onChange` to\n rebuild when they change. Rows whose tenant is `NULL` (the global slice) do not\n match tenant-scoped related rows, because `NULL = NULL` is not true in SQL.\n- **Saved views and snapshots notice definition changes.** A column's expression, filter and the joins it reads are part of its descriptor (`semantics`) and so of the report definition fingerprint; changing one invalidates stored views and export snapshots. Reports without joins or expressions keep their existing fingerprints.\n- **No drilldown by joined or computed keys.** A row grouped by a joined column or\n a computed value cannot be bound back to source rows by a source column, so\n `buildReportDrilldownQuery()` refuses such reports.\n\nThe runtime-report grammar stays closed: runtime reports have no joins or\nexpressions.\n\n## Refresh modes\n\n- `rebuild` replaces the materialized result.\n- `incremental` recomputes groups affected after a source watermark and removes\n groups that become empty.\n- TTL-backed collections refresh before reads when the report is stale.\n- `ReportScheduleRunner` and `registerReportRefreshInterceptor()` enqueue\n durable refresh jobs through [`smrt-jobs`](../jobs/README.md).\n\nIncremental sources need watermark and soft-delete columns, normally\n`updatedAt` and `deletedAt`. Tenant-scoped aggregate SQL explicitly filters\n`tenant_id`; normal collection interceptors cannot secure a raw aggregate.\n\n## Public entry points\n\nThe package exposes focused subpaths for consumers that want only the compiler,\ndecorators, refresh engine, scheduler, state models, or aggregate compatibility\nhelpers:\n\n```text\n@happyvertical/smrt-reports\n@happyvertical/smrt-reports/compiler\n@happyvertical/smrt-reports/decorators\n@happyvertical/smrt-reports/refresh\n@happyvertical/smrt-reports/scheduler\n@happyvertical/smrt-reports/state\n@happyvertical/smrt-reports/aggregate\n```\n\n## Report adapter\n\nThe package also exports a transport-neutral adapter for report surfaces:\n\n```ts\nimport {\n buildReportAdapterDescriptor,\n buildReportDrilldownQuery,\n queryReportMaterializedRows,\n reportMaterializedRowKey,\n splitReportFilterScopes,\n} from '@happyvertical/smrt-reports';\n\nconst descriptor = await buildReportAdapterDescriptor(MonthlyRevenue, {\n tenantScope: 'current',\n});\nconst reports = await MonthlyRevenueCollection.create({ db: 'app.db' });\nconst result = await queryReportMaterializedRows(\n MonthlyRevenue,\n {\n version: 1,\n requestId: 'monthly-revenue-first-page',\n mode: 'rows',\n projection: ['id', 'customer_id', 'revenue'],\n filter: {\n kind: 'all',\n filters: [\n {\n kind: 'condition',\n field: 'customer_id',\n operator: 'eq',\n value: 'customer-42',\n },\n {\n kind: 'condition',\n field: 'revenue',\n operator: 'gte',\n value: 1000,\n },\n ],\n },\n page: { kind: 'offset', offset: 0, limit: 25 },\n sort: [{ field: 'revenue', direction: 'desc' }],\n },\n {\n collection: reports,\n // Preserve the resource identity of the descriptor selected above.\n adapter: { tenantScope: 'current' },\n },\n);\nconst rowKey = reportMaterializedRowKey(result.rows[0]);\nconst drilldown = await buildReportDrilldownQuery(MonthlyRevenue, result.rows[0]);\n```\n\n`ReportAdapterDescriptor` is deterministic JSON with a stable resource id,\n`id` as the identity field, typed report columns, a canonical `DataQuerySchema`,\nand structural DataTable hints. The hints are deliberately not a `smrt-ui`\ndependency. Consumers may map the descriptor to their own presentation layer.\nThe adapter exposes only persisted report columns and the primary key: transient,\nsystem, and non-column fields are not surfaced. Sensitive/secret fields and\nfields with a `readPermission` are excluded without a principal, so the\ndescriptor fails closed.\n\nThe `dataTable.columns` entries carry neutral `headerPath`, `valueFormat`,\nalignment, role, and responsive hints. Grouping fields, time buckets, and\naggregate measures receive deterministic multi-level header ancestry; a\nconsumer can override any column by stable id with\n`buildReportAdapterDescriptor(..., { dataTable: { columns: { ... } } })`.\n`valueFormat` is an instruction for the rendering boundary only: rows returned\nby `queryReportMaterializedRows()` retain their raw JSON-safe values for\nsorting, exports, and agents. Use `dataTable.structuralRows` for a computed\nsummary, subtotal, aggregate, or footer. Each is marked `selection: 'excluded'`\nand `actions: 'excluded'`, and must be passed to the consumer table's structural\nrow surface rather than its selectable data rows.\n\n`queryReportMaterializedRows()` is the bounded read slice for already-materialized\nrows. It supports projection, offset/limit paging (default limit 50),\ndeterministic multi-sort (with `id` as the final tie-break), typed filters, and\ndatabase-backed dimension facets. A descriptor marks group/time fields as\n`filterScope: 'where'` and aggregate measures as `filterScope: 'having'`; use\n`splitReportFilterScopes()` when constructing a live source query. An AND may\ncombine the two scopes, but an OR or NOT cannot mix them, because moving either\nside across a source `WHERE`/`HAVING` boundary would change its meaning.\n\nMaterialized query results normalize hydrated values against their declared\ncolumn types. Objects in scalar columns become JSON text; JSON columns retain\nstructured values. Date-only and timezone-less timestamps use UTC, matching\nSQLite storage, and temporal facet buckets follow the same rule. Strings over\n4096 characters are shortened with `truncated` and a warning, except row IDs:\nidentities are never rewritten, and unsupported IDs fail validation. Unsafe bigint\nvalues fail instead of silently losing precision.\n\nThe materialized collection executes the normalized, allowlisted predicate as\nparameterized SQL and applies it identically to rows, totals, and facets. It\nnever accepts raw SQL, source field paths, tenant ids, or principal ids.\nThe descriptor's `queryExecution` contract declares three delivery choices:\n`visible` (the default) returns rows for an already-authorized surface,\n`silent` returns the same bounded result while making no visible-surface change,\nand `background` delegates a normalized, authority-free task to the application's\n`enqueueBackgroundQuery` host. A background result is only a queue handle, never\nmaterialized rows. The host retains the authenticated principal, tenant, report\ndefinition, field policy, database, and eventual job execution; none can be\nsupplied in a query request or background task.\nWhen a consumer selects a descriptor with `ReportAdapterOptions`, pass those\nsame options through the query's `adapter` option so returned and background\ntask resource ids stay aligned with the selected descriptor.\n`buildReportDrilldownQuery()` carries only the row's declared groups/buckets\nand a fixed inheritance contract for the current principal, tenant, report\ndefinition, and field policy; an authenticated source adapter must enforce that\ncontract before it reads source records. Time buckets remain declarative so the\nsource adapter keeps the report's database/timezone semantics. Every returned\nrow must have a non-empty string `id`; use that value, never a display or page\nindex, for row identity.\n\nWhen no collection is injected, reads resolve the registered report collection\nthrough `ObjectRegistry`, allowing normal s-m-r-t collection interceptors to enforce\ntenant filtering. `tenantScoped` and `tenantField` in the descriptor are true\nonly when the report is actually registered with tenant metadata; a scope string\nalone is not an authority boundary. An injected collection is application-owned\nand must provide the equivalent tenant boundary. Raw aggregate refreshes still\nneed explicit tenant predicates as described above.\n\nThe descriptor's `refresh` section declares mode, triggers, stale-read behavior,\nand a permissioned, audited `refresh` action with `preview` and `apply` phases.\nThe adapter itself stays read-only. Call `getReportLifecycle()` for a tenant-safe\nsnapshot of current, stale, refreshing, lock-skipped, or failed materialization\nstate; it redacts lock owners, raw errors, and tenant-fanout identifiers. Pass a\n`lifecycle` option to `queryReportMaterializedRows()` only when a consumer needs\nthat context; the result then distinguishes a current, stale, or read-triggered\nrefresh. `previewReportRefresh()` and `applyReportRefresh()` require an\napplication action host to authorize and audit the caller before a durable\nreport-refresh job is queued. Manual refresh hosts must also return a versioned,\nnon-secret `executionAuthority` binding. Each worker process registers the named\nhost with `registerReportRefreshExecutionAuthorityHost()`; the task checks the\npersisted tenant binding, resolves current membership and permission, and records\nan allowed or denied execution audit immediately before refresh. Every enqueue\npath also receives a `DurableJobPayloadSigner`, and every worker registers it\nwith `registerReportRefreshJobIntegritySigner()`. This authenticates the task\ntarget, trigger, tenant scope, authority reference, and payload across storage;\nthe signing key is never persisted. Scheduled and on-change maintenance jobs\nremain system-authority jobs and do not carry an initiating user, but their job\npayloads use the same integrity boundary. Only a registered `SmrtReportCollection` can\nsynchronously refresh a stale read, and only when its TTL policy is positive and\nnot manual.\n\n### Scheduled refresh lifecycle\n\nDeclare `refresh: { schedule: '*/5 * * * *', tenantFanout: 'discover' }`\non a tenant-scoped report to discover distinct non-null source tenants each\nscheduled run. Include scopes still present in the materialized table so a\nthe next rebuild removes stale groups for tenants losing their final source row.\nDiscovery preserves the configured refresh mode. Incremental reports still need\na `fullRebuildSchedule` to catch hard deletions that do not advance a source\nwatermark. Provision schedules with `ensureReportRefreshSchedules({ db,\nreports })`; no discovered scopes means no work, and discovery never refreshes\nthe global slice.\nThe worker uses the registered source/report tenant columns and its supplied\nmaintenance executor. Discovery does not grant database privileges or widen a\ntenant-bound or manual job. Keep `tenantFanout: true` with explicit `tenantIds`\nwhen the host owns a fixed tenant list.\n\nInitialize a `ReportScheduleRunner` and a jobs `TaskRunner` against the migrated\ndatabase, then call `const unbind = schedules.bindTaskRunner(tasks)` before\nstarting them. This connects terminal job events to schedule counters, freeing\nthe concurrency slot after success or failure. Repeated binding is idempotent;\ncall `unbind()` on shutdown. Listen for `runner:error` to detect failed counter\nupdates. Persisted failure messages use the jobs package redaction policy.\nDurable payload signing and execution-time authority checks remain\nrequired; completion accounting uses the signed schedule identity.\n\nRepeated schedule provisioning inserts missing identities and preserves existing\nhistory, next-run time, running count, and operator settings. A different cron,\nmode, or tenant scope identifies a different schedule; explicitly disable obsolete\nschedules when changing those settings.\n\n### Saved views and snapshot exports\n\n`normalizeReportSavedView()` and `restoreReportSavedView()` provide the\nserializable view boundary. A storage host owns the saved view's tenant and\nowner; on every restore it must pass the stored payload through the current\ndescriptor. That reapplies field, projection, sorting, grouping, and definition\npolicy, so a stale view cannot reveal a field that is no longer allowed.\n`migrateReportSavedView()` upgrades the original unversioned (or explicit v0)\nlayout to v1 before that current-policy validation; unsupported future versions\nfail clearly rather than being guessed.\n\nBuild an export from a completed materialized-row read with\n`createReportExportSnapshot()`, supplying an opaque binding from the\napplication's immutable materialization-snapshot host, then call\n`createReportExportRequest()`. The snapshot fixes the canonical query\nfingerprint, normalized projection and sort, exact row count, `asOf`,\n`refreshedAt`, stale state, and definition fingerprint. Every request also\ncontains a deterministic offset-page read plan; a renderer begins at offset zero\nand advances by its validated page size until the exact bounded row count is\nreached. Use `createReportExportPageRequest()` for each page; it preserves the\nfrozen query semantics while replacing only visible pagination.\n\nEvery request is bounded by rows, bytes, and deadline; exports over the\nforeground row limit become an authority-free background handoff. Use\n`previewReportExport()` and `applyReportExport()` with the same application\naction host for human and agent callers. The host authorizes and audits the\nfixed `reports.export` action; exports containing personal, sensitive, or secret\ncolumns require explicit confirmation.\n\nPreview, apply, and every worker call `validateReportExportExecution()`, which\nrequires the host to prove that the opaque binding still resolves to the exact\nimmutable materialization snapshot under its current principal, tenant, report\ndefinition, and field policy. If it cannot, the operation fails rather than\nrelabelling newer rows with an old `asOf`. Artifact metadata has no URL or\ndownload token; before serving it, call `validateReportExportArtifact()` to\nreject expiry, definition drift, and out-of-bounds progress, then apply the\nhost's current authorization and snapshot validation again.\n\n## Runtime reports\n\nA report can also be defined at runtime as data. `RuntimeReportSpec` is a closed,\nversioned structure (source id, dimensions, measures, filters, having, sort,\nchart hint) with no free-form query text. `compileRuntimeReportSpec()` checks it\nagainst a server-owned source allow-list, field policy (sensitive and\npermission-gated fields are not nameable), the caller's permissions, and tenant\nisolation, then targets the same aggregate plan as declared reports.\n`RuntimeReport` stores validated specs per tenant, and a stored spec is\nre-compiled for the running user on every run. Result rows are not stored. A row\ncan only be inserted, or have its spec changed, through `saveRuntimeReport()`\nwith the spec hash a human confirmed; the model layer refuses every other write. The\nchat package offers matching assistant tools that propose a spec, preview it,\nand save only after a human confirms. See\n[`agents/runtime-reports.md`](./agents/runtime-reports.md).\n\n## Browser components\n\n`@happyvertical/smrt-reports/svelte` exports saved-report and detail screens,\na confirmation card, a report/measure picker, and a shared-chart result view.\nThey accept a principal-scoped browser transport and show an unavailable state\nwhen no server is supplied. See the [browser integration contract](./agents/runtime-report-browser.md)\nfor route-host identity and capability props, confirmation wiring, recipe\nsurfaces, and playground previews.\n\n## Development\n\n```bash\npnpm --filter @happyvertical/smrt-reports test\npnpm --filter @happyvertical/smrt-reports typecheck\npnpm --filter @happyvertical/smrt-reports build\n```\n\nSee [`AGENTS.md`](./AGENTS.md) for refresh, schema, and tenancy invariants.\n"
|
|
1282
1282
|
}
|
|
1283
1283
|
],
|
|
1284
1284
|
"recipes": [
|
package/dist/state.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ObjectRegistry, SmrtCollection, SmrtObject, field, smrt } from "@happyvertical/smrt-core";
|
|
2
2
|
import { TenantScoped, tenantId } from "@happyvertical/smrt-tenancy";
|
|
3
3
|
//#region src/__smrt-register__.ts
|
|
4
|
-
ObjectRegistry.registerPackageManifest(JSON.parse(`{"version":"1.0.0","timestamp":0,"packageName":"@happyvertical/smrt-reports","packageVersion":"0.57.31","objects":{"@happyvertical/smrt-reports:SmrtReport":{"name":"smrtreport","className":"SmrtReport","qualifiedName":"@happyvertical/smrt-reports:SmrtReport","collection":"smrtreports","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/report.ts","packageName":"@happyvertical/smrt-reports","fields":{"refreshedAt":{"type":"datetime","required":false}},"methods":{"isStale":{"name":"isStale","async":false,"parameters":[{"name":"ttlMs","type":"number","optional":true}],"returnType":"boolean","isStatic":false,"isPublic":true},"refresh":{"name":"refresh","async":true,"parameters":[{"name":"options","type":"Omit<ReportRefreshOptions, 'db'>","optional":true}],"returnType":"Promise<ReportRefreshResult>","isStatic":false,"isPublic":true}},"decoratorConfig":{},"extends":"SmrtObject","exportName":"SmrtReport","collectionExportName":"SmrtReportCollection","importPath":"@happyvertical/smrt-reports"},"@happyvertical/smrt-reports:SmrtReportCollection":{"name":"smrtreportcollection","className":"SmrtReportCollection","qualifiedName":"@happyvertical/smrt-reports:SmrtReportCollection","collection":"smrtreports","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/report.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{"refresh":{"name":"refresh","async":true,"parameters":[{"name":"options","type":"Omit<ReportRefreshOptions, 'db'>","optional":true}],"returnType":"Promise<ReportRefreshResult>","isStatic":false,"isPublic":true},"list":{"name":"list","async":true,"parameters":[{"name":"options","type":"SmrtListOptions<ModelType>","optional":true}],"returnType":"Promise<SmrtObject[] | Record<string, unknown>[]>","isStatic":false,"isPublic":true},"get":{"name":"get","async":true,"parameters":[{"name":"filter","type":"any","optional":false,"typeUnresolved":true},{"name":"options","type":"any","optional":true,"typeUnresolved":true}],"returnType":"Promise<ModelType | null>","isStatic":false,"isPublic":true}},"decoratorConfig":{},"extends":"SmrtCollection","extendsTypeArg":"ModelType","exportName":"SmrtReportCollection","collectionExportName":"SmrtReportCollectionCollection","importPath":"@happyvertical/smrt-reports"},"@happyvertical/smrt-reports:RuntimeReport":{"name":"runtimereport","className":"RuntimeReport","qualifiedName":"@happyvertical/smrt-reports:RuntimeReport","collection":"runtimereports","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/runtime-report.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"title":{"type":"text","required":false,"_meta":{}},"description":{"type":"text","required":false,"_meta":{}},"sourceId":{"type":"text","required":false,"_meta":{}},"spec":{"type":"text","required":true,"_meta":{"required":true}},"specHash":{"type":"text","required":false,"_meta":{}},"status":{"type":"text","required":true,"_meta":{"required":true},"enum":["active","archived"]},"createdByUserId":{"type":"text","required":false,"_meta":{}}},"methods":{"run":{"name":"run","async":true,"parameters":[],"returnType":"Promise<RuntimeReportResult>","isStatic":false,"isPublic":true},"archive":{"name":"archive","async":true,"parameters":[{"name":"options","type":"object","optional":false,"memberTypes":["boolean"]}],"returnType":"Promise<object>","isStatic":false,"isPublic":true},"getSpec":{"name":"getSpec","async":false,"parameters":[],"returnType":"RuntimeReportSpec","isStatic":false,"isPublic":true},"setSpec":{"name":"setSpec","async":false,"parameters":[{"name":"spec","type":"RuntimeReportSpec","optional":false}],"returnType":"void","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"runtime_reports","indexes":[{"name":"idx_runtime_reports_confirm","columns":["tenantId","createdByUserId","specHash","status"]}],"operationPermissions":{"run":{"action":"read"},"archive":{"action":"create","databaseActions":["SELECT","UPDATE"]}},"api":{"include":["list","get","create","run","archive"],"principalContext":true,"routes":{"run":{"method":"POST","scope":"item","effect":"read","idempotent":true,"openWorld":false},"archive":{"method":"POST","scope":"item","effect":"write","idempotent":true,"openWorld":false}}},"mcp":{"include":["list","get","run","archive"]},"cli":{"include":["list","get","run","archive"]},"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"RuntimeReport","collectionExportName":"RuntimeReportCollection","displayLabelField":"title","validationRules":[{"field":"spec","rule":"required","fieldType":"text"},{"field":"status","rule":"required","fieldType":"text"}],"schema":{"tableName":"runtime_reports","ddl":"CREATE TABLE IF NOT EXISTS \\"runtime_reports\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"title\\" TEXT,\\n \\"description\\" TEXT,\\n \\"source_id\\" TEXT,\\n \\"spec\\" TEXT NOT NULL,\\n \\"spec_hash\\" TEXT,\\n \\"status\\" TEXT NOT NULL,\\n \\"created_by_user_id\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"title":{"type":"TEXT","notNull":false,"unique":false},"description":{"type":"TEXT","notNull":false,"unique":false},"source_id":{"type":"TEXT","notNull":false,"unique":false},"spec":{"type":"TEXT","notNull":true,"unique":false},"spec_hash":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"created_by_user_id":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"runtime_reports_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"idx_runtime_reports_confirm","columns":["tenant_id","created_by_user_id","spec_hash","status"]},{"name":"runtime_reports_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"04a92513"},"importPath":"@happyvertical/smrt-reports"},"@happyvertical/smrt-reports:RuntimeReportCollection":{"name":"runtimereportcollection","className":"RuntimeReportCollection","qualifiedName":"@happyvertical/smrt-reports:RuntimeReportCollection","collection":"runtimereports","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/runtime-report.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{},"decoratorConfig":{"tableName":"runtime_reports","api":{"include":["list","get","create"]},"mcp":{"include":["list","get"]},"cli":{"include":["list","get"]}},"extends":"SmrtCollection","extendsTypeArg":"RuntimeReport","exportName":"RuntimeReportCollection","collectionExportName":"RuntimeReportCollectionCollection","schema":{"tableName":"runtime_reports","ddl":"CREATE TABLE IF NOT EXISTS \\"runtime_reports\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"title\\" TEXT,\\n \\"description\\" TEXT,\\n \\"source_id\\" TEXT,\\n \\"spec\\" TEXT NOT NULL,\\n \\"spec_hash\\" TEXT,\\n \\"status\\" TEXT NOT NULL,\\n \\"created_by_user_id\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"title":{"type":"TEXT","notNull":false,"unique":false},"description":{"type":"TEXT","notNull":false,"unique":false},"source_id":{"type":"TEXT","notNull":false,"unique":false},"spec":{"type":"TEXT","notNull":true,"unique":false},"spec_hash":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"created_by_user_id":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"runtime_reports_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"idx_runtime_reports_confirm","columns":["tenant_id","created_by_user_id","spec_hash","status"]},{"name":"runtime_reports_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"04a92513"},"importPath":"@happyvertical/smrt-reports"},"@happyvertical/smrt-reports:SmrtReportRefreshTask":{"name":"smrtreportrefreshtask","className":"SmrtReportRefreshTask","qualifiedName":"@happyvertical/smrt-reports:SmrtReportRefreshTask","collection":"smrtreportrefreshtasks","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/scheduler.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"reportClass":{"type":"text","required":true,"_meta":{"required":true}},"mode":{"type":"text","required":true,"_meta":{"required":true},"enum":["rebuild","incremental"]},"trigger":{"type":"text","required":true,"_meta":{"required":true},"enum":["manual","schedule","change","ttl","job"]},"args":{"type":"json","required":false,"_meta":{}}},"methods":{"run":{"name":"run","async":true,"parameters":[{"name":"args","type":"ReportRefreshJobArgs","optional":true},{"name":"context","type":"JobExecutionContext","optional":true}],"returnType":"Promise<unknown>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"_smrt_report_refresh_tasks","api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"SmrtReportRefreshTask","collectionExportName":"SmrtReportRefreshTaskCollection","validationRules":[{"field":"reportClass","rule":"required","fieldType":"text"},{"field":"mode","rule":"required","fieldType":"text"},{"field":"trigger","rule":"required","fieldType":"text"}],"schema":{"tableName":"_smrt_report_refresh_tasks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_refresh_tasks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"mode\\" TEXT NOT NULL,\\n \\"trigger\\" TEXT NOT NULL,\\n \\"args\\" JSON\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"mode":{"type":"TEXT","notNull":true,"unique":false},"trigger":{"type":"TEXT","notNull":true,"unique":false},"args":{"type":"JSON","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_refresh_tasks_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"_smrt_report_refresh_tasks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"c9142042"},"importPath":"@happyvertical/smrt-reports/scheduler"},"@happyvertical/smrt-reports:SmrtPrincipalReportRefreshTask":{"name":"smrtprincipalreportrefreshtask","className":"SmrtPrincipalReportRefreshTask","qualifiedName":"@happyvertical/smrt-reports:SmrtPrincipalReportRefreshTask","collection":"smrtprincipalreportrefreshtasks","description":"Worker target whose authority requirement cannot be downgraded by job args.","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/scheduler.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"generated":true,"source":"tenantScoped_decorator","sqlType":"UUID","__tenancy":{"isTenantIdField":true,"mode":"optional","field":"tenantId","autoFilter":true,"autoPopulate":true,"allowSuperAdminBypass":false}}}},"methods":{"run":{"name":"run","async":true,"parameters":[{"name":"args","type":"ReportRefreshJobArgs","optional":true},{"name":"context","type":"JobExecutionContext","optional":true}],"returnType":"Promise<unknown>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"_smrt_principal_report_refresh_tasks","api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtReportRefreshTask","exportName":"SmrtPrincipalReportRefreshTask","collectionExportName":"SmrtPrincipalReportRefreshTaskCollection","schema":{"tableName":"_smrt_principal_report_refresh_tasks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_principal_report_refresh_tasks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_principal_report_refresh_tasks_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"_smrt_principal_report_refresh_tasks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"226a3b97"},"importPath":"@happyvertical/smrt-reports/scheduler"},"@happyvertical/smrt-reports:SmrtReportRun":{"name":"smrtreportrun","className":"SmrtReportRun","qualifiedName":"@happyvertical/smrt-reports:SmrtReportRun","collection":"smrtreportruns","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"scopeKey":{"type":"text","required":true,"_meta":{"required":true}},"reportClass":{"type":"text","required":true,"_meta":{"required":true}},"sourceClass":{"type":"text","required":true,"_meta":{"required":true}},"mode":{"type":"text","required":true,"_meta":{"required":true},"enum":["rebuild","incremental"]},"trigger":{"type":"text","required":true,"_meta":{"required":true},"enum":["manual","schedule","change","ttl","job"]},"status":{"type":"text","required":true,"description":"Whether the refresh is running, finished, failed or was skipped.","_meta":{"required":true,"description":"Whether the refresh is running, finished, failed or was skipped."},"enum":["running","success","failed","skipped"]},"startedAt":{"type":"datetime","required":true,"description":"When the refresh began.","_meta":{"required":true,"description":"When the refresh began."}},"completedAt":{"type":"datetime","required":false,"description":"When the refresh finished. Empty while it is still running.","_meta":{"nullable":true,"description":"When the refresh finished. Empty while it is still running."}},"rowCount":{"type":"integer","required":true,"description":"How many rows the report held after the refresh.","_meta":{"required":true,"description":"How many rows the report held after the refresh."}},"changedGroupCount":{"type":"integer","required":true,"_meta":{"required":true}},"watermarkBefore":{"type":"text","required":false,"_meta":{"nullable":true}},"watermarkAfter":{"type":"text","required":false,"_meta":{"nullable":true}},"error":{"type":"text","required":false,"description":"Why the refresh failed. Empty when it worked.","_meta":{"nullable":true,"description":"Why the refresh failed. Empty when it worked."}},"metadata":{"type":"json","required":false,"_meta":{}}},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_runs","api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"SmrtReportRun","collectionExportName":"SmrtReportRunCollection","validationRules":[{"field":"scopeKey","rule":"required","fieldType":"text"},{"field":"reportClass","rule":"required","fieldType":"text"},{"field":"sourceClass","rule":"required","fieldType":"text"},{"field":"mode","rule":"required","fieldType":"text"},{"field":"trigger","rule":"required","fieldType":"text"},{"field":"status","rule":"required","fieldType":"text"},{"field":"startedAt","rule":"required","fieldType":"datetime"},{"field":"rowCount","rule":"required","fieldType":"integer"},{"field":"changedGroupCount","rule":"required","fieldType":"integer"}],"schema":{"tableName":"_smrt_report_runs","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_runs\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"source_class\\" TEXT NOT NULL,\\n \\"mode\\" TEXT NOT NULL,\\n \\"trigger\\" TEXT NOT NULL,\\n \\"status\\" TEXT NOT NULL,\\n \\"started_at\\" TIMESTAMP NOT NULL,\\n \\"completed_at\\" TIMESTAMP,\\n \\"row_count\\" INTEGER NOT NULL,\\n \\"changed_group_count\\" INTEGER NOT NULL,\\n \\"watermark_before\\" TEXT,\\n \\"watermark_after\\" TEXT,\\n \\"error\\" TEXT,\\n \\"metadata\\" JSON\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"source_class":{"type":"TEXT","notNull":true,"unique":false},"mode":{"type":"TEXT","notNull":true,"unique":false},"trigger":{"type":"TEXT","notNull":true,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"started_at":{"type":"TIMESTAMP","notNull":true,"unique":false},"completed_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"row_count":{"type":"INTEGER","notNull":true,"unique":false},"changed_group_count":{"type":"INTEGER","notNull":true,"unique":false},"watermark_before":{"type":"TEXT","notNull":false,"unique":false},"watermark_after":{"type":"TEXT","notNull":false,"unique":false},"error":{"type":"TEXT","notNull":false,"unique":false},"metadata":{"type":"JSON","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_runs_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"_smrt_report_runs_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"54ff5048"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportRunCollection":{"name":"smrtreportruncollection","className":"SmrtReportRunCollection","qualifiedName":"@happyvertical/smrt-reports:SmrtReportRunCollection","collection":"smrtreportruns","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_runs","api":false,"mcp":false,"cli":{"include":["list","get"],"skipApiCheck":true}},"extends":"SmrtCollection","extendsTypeArg":"SmrtReportRun","exportName":"SmrtReportRunCollection","collectionExportName":"SmrtReportRunCollectionCollection","schema":{"tableName":"_smrt_report_runs","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_runs\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"source_class\\" TEXT NOT NULL,\\n \\"mode\\" TEXT NOT NULL,\\n \\"trigger\\" TEXT NOT NULL,\\n \\"status\\" TEXT NOT NULL,\\n \\"started_at\\" TIMESTAMP NOT NULL,\\n \\"completed_at\\" TIMESTAMP,\\n \\"row_count\\" INTEGER NOT NULL,\\n \\"changed_group_count\\" INTEGER NOT NULL,\\n \\"watermark_before\\" TEXT,\\n \\"watermark_after\\" TEXT,\\n \\"error\\" TEXT,\\n \\"metadata\\" JSON\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"source_class":{"type":"TEXT","notNull":true,"unique":false},"mode":{"type":"TEXT","notNull":true,"unique":false},"trigger":{"type":"TEXT","notNull":true,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"started_at":{"type":"TIMESTAMP","notNull":true,"unique":false},"completed_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"row_count":{"type":"INTEGER","notNull":true,"unique":false},"changed_group_count":{"type":"INTEGER","notNull":true,"unique":false},"watermark_before":{"type":"TEXT","notNull":false,"unique":false},"watermark_after":{"type":"TEXT","notNull":false,"unique":false},"error":{"type":"TEXT","notNull":false,"unique":false},"metadata":{"type":"JSON","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_runs_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"_smrt_report_runs_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"54ff5048"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportWatermark":{"name":"smrtreportwatermark","className":"SmrtReportWatermark","qualifiedName":"@happyvertical/smrt-reports:SmrtReportWatermark","collection":"smrtreportwatermarks","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"scopeKey":{"type":"text","required":true,"_meta":{"required":true}},"reportClass":{"type":"text","required":true,"_meta":{"required":true}},"sourceClass":{"type":"text","required":true,"_meta":{"required":true}},"watermarkColumn":{"type":"text","required":true,"_meta":{"required":true}},"watermarkValue":{"type":"text","required":false,"_meta":{"nullable":true}},"lastRunId":{"type":"text","required":false,"_meta":{"nullable":true}}},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_watermarks","conflictColumns":["report_class","scope_key","source_class","watermark_column"],"api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"}},"extends":"SmrtObject","exportName":"SmrtReportWatermark","collectionExportName":"SmrtReportWatermarkCollection","validationRules":[{"field":"scopeKey","rule":"required","fieldType":"text"},{"field":"reportClass","rule":"required","fieldType":"text"},{"field":"sourceClass","rule":"required","fieldType":"text"},{"field":"watermarkColumn","rule":"required","fieldType":"text"}],"schema":{"tableName":"_smrt_report_watermarks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_watermarks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"source_class\\" TEXT NOT NULL,\\n \\"watermark_column\\" TEXT NOT NULL,\\n \\"watermark_value\\" TEXT,\\n \\"last_run_id\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"source_class":{"type":"TEXT","notNull":true,"unique":false},"watermark_column":{"type":"TEXT","notNull":true,"unique":false},"watermark_value":{"type":"TEXT","notNull":false,"unique":false},"last_run_id":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_watermarks_report_class_scope_key_idx","columns":["report_class","scope_key","source_class","watermark_column"],"unique":true},{"name":"_smrt_report_watermarks_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_watermarks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"dac9d57a"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportWatermarkCollection":{"name":"smrtreportwatermarkcollection","className":"SmrtReportWatermarkCollection","qualifiedName":"@happyvertical/smrt-reports:SmrtReportWatermarkCollection","collection":"smrtreportwatermarks","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_watermarks","api":false,"mcp":false,"cli":{"include":["list","get"],"skipApiCheck":true}},"extends":"SmrtCollection","extendsTypeArg":"SmrtReportWatermark","exportName":"SmrtReportWatermarkCollection","collectionExportName":"SmrtReportWatermarkCollectionCollection","schema":{"tableName":"_smrt_report_watermarks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_watermarks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"source_class\\" TEXT NOT NULL,\\n \\"watermark_column\\" TEXT NOT NULL,\\n \\"watermark_value\\" TEXT,\\n \\"last_run_id\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"source_class":{"type":"TEXT","notNull":true,"unique":false},"watermark_column":{"type":"TEXT","notNull":true,"unique":false},"watermark_value":{"type":"TEXT","notNull":false,"unique":false},"last_run_id":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_watermarks_report_class_scope_key_idx","columns":["report_class","scope_key","source_class","watermark_column"],"unique":true},{"name":"_smrt_report_watermarks_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_watermarks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"dac9d57a"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportLock":{"name":"smrtreportlock","className":"SmrtReportLock","qualifiedName":"@happyvertical/smrt-reports:SmrtReportLock","collection":"smrtreportlocks","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"scopeKey":{"type":"text","required":true,"_meta":{"required":true}},"reportClass":{"type":"text","required":true,"_meta":{"required":true}},"ownerId":{"type":"text","required":false,"_meta":{"nullable":true}},"acquiredAt":{"type":"datetime","required":false,"_meta":{"nullable":true}},"heartbeatAt":{"type":"datetime","required":false,"_meta":{"nullable":true}},"expiresAt":{"type":"datetime","required":false,"_meta":{"nullable":true}}},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_locks","conflictColumns":["report_class","scope_key"],"api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"}},"extends":"SmrtObject","exportName":"SmrtReportLock","collectionExportName":"SmrtReportLockCollection","validationRules":[{"field":"scopeKey","rule":"required","fieldType":"text"},{"field":"reportClass","rule":"required","fieldType":"text"}],"schema":{"tableName":"_smrt_report_locks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_locks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"owner_id\\" TEXT,\\n \\"acquired_at\\" TIMESTAMP,\\n \\"heartbeat_at\\" TIMESTAMP,\\n \\"expires_at\\" TIMESTAMP\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"owner_id":{"type":"TEXT","notNull":false,"unique":false},"acquired_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"heartbeat_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"expires_at":{"type":"TIMESTAMP","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_locks_report_class_scope_key_idx","columns":["report_class","scope_key"],"unique":true},{"name":"_smrt_report_locks_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_locks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"4a2043f9"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportLockCollection":{"name":"smrtreportlockcollection","className":"SmrtReportLockCollection","qualifiedName":"@happyvertical/smrt-reports:SmrtReportLockCollection","collection":"smrtreportlocks","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_locks","api":false,"mcp":false,"cli":{"include":["list","get"],"skipApiCheck":true}},"extends":"SmrtCollection","extendsTypeArg":"SmrtReportLock","exportName":"SmrtReportLockCollection","collectionExportName":"SmrtReportLockCollectionCollection","schema":{"tableName":"_smrt_report_locks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_locks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"owner_id\\" TEXT,\\n \\"acquired_at\\" TIMESTAMP,\\n \\"heartbeat_at\\" TIMESTAMP,\\n \\"expires_at\\" TIMESTAMP\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"owner_id":{"type":"TEXT","notNull":false,"unique":false},"acquired_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"heartbeat_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"expires_at":{"type":"TIMESTAMP","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_locks_report_class_scope_key_idx","columns":["report_class","scope_key"],"unique":true},{"name":"_smrt_report_locks_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_locks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"4a2043f9"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportSchedule":{"name":"smrtreportschedule","className":"SmrtReportSchedule","qualifiedName":"@happyvertical/smrt-reports:SmrtReportSchedule","collection":"smrtreportschedules","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"scopeKey":{"type":"text","required":true,"_meta":{"required":true}},"reportClass":{"type":"text","required":true,"_meta":{"required":true}},"cron":{"type":"text","required":true,"description":"When the report refreshes, as a cron schedule such as 0 6 * * * for 6 am daily.","_meta":{"required":true,"description":"When the report refreshes, as a cron schedule such as 0 6 * * * for 6 am daily."}},"trigger":{"type":"text","required":true,"_meta":{"required":true},"enum":["manual","schedule","change","ttl","job"]},"mode":{"type":"text","required":true,"description":"Rebuild recomputes the whole report. Incremental updates only what changed.","_meta":{"required":true,"description":"Rebuild recomputes the whole report. Incremental updates only what changed."},"enum":["rebuild","incremental"]},"enabled":{"type":"boolean","required":true,"description":"Turn off to stop refreshing without deleting the schedule.","_meta":{"required":true,"description":"Turn off to stop refreshing without deleting the schedule."}},"status":{"type":"text","required":true,"description":"Whether the schedule is active, paused, disabled or in error.","_meta":{"required":true,"description":"Whether the schedule is active, paused, disabled or in error."},"enum":["active","paused","disabled","error"]},"nextRun":{"type":"datetime","required":false,"description":"When the report is next due to refresh.","_meta":{"nullable":true,"description":"When the report is next due to refresh."}},"lastRun":{"type":"datetime","required":false,"description":"When the report last started a scheduled refresh.","_meta":{"nullable":true,"description":"When the report last started a scheduled refresh."}},"lastStatus":{"type":"text","required":false,"description":"Whether the last scheduled refresh worked or failed.","_meta":{"nullable":true,"description":"Whether the last scheduled refresh worked or failed."},"enum":["success","failed"]},"lastError":{"type":"text","required":false,"description":"Why the last scheduled refresh failed. Empty when it worked.","_meta":{"nullable":true,"description":"Why the last scheduled refresh failed. Empty when it worked."}},"runCount":{"type":"integer","required":true,"_meta":{"required":true}},"successCount":{"type":"integer","required":true,"_meta":{"required":true}},"failureCount":{"type":"integer","required":true,"_meta":{"required":true}},"runningCount":{"type":"integer","required":true,"_meta":{"required":true}},"maxConcurrent":{"type":"integer","required":true,"_meta":{"required":true}},"queue":{"type":"text","required":true,"_meta":{"required":true}},"priority":{"type":"integer","required":true,"_meta":{"required":true}},"timeout":{"type":"integer","required":true,"_meta":{"required":true}}},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_schedules","conflictColumns":["report_class","scope_key","cron","mode"],"api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"}},"extends":"SmrtObject","exportName":"SmrtReportSchedule","collectionExportName":"SmrtReportScheduleCollection","validationRules":[{"field":"scopeKey","rule":"required","fieldType":"text"},{"field":"reportClass","rule":"required","fieldType":"text"},{"field":"cron","rule":"required","fieldType":"text"},{"field":"trigger","rule":"required","fieldType":"text"},{"field":"mode","rule":"required","fieldType":"text"},{"field":"enabled","rule":"required","fieldType":"boolean"},{"field":"status","rule":"required","fieldType":"text"},{"field":"runCount","rule":"required","fieldType":"integer"},{"field":"successCount","rule":"required","fieldType":"integer"},{"field":"failureCount","rule":"required","fieldType":"integer"},{"field":"runningCount","rule":"required","fieldType":"integer"},{"field":"maxConcurrent","rule":"required","fieldType":"integer"},{"field":"queue","rule":"required","fieldType":"text"},{"field":"priority","rule":"required","fieldType":"integer"},{"field":"timeout","rule":"required","fieldType":"integer"}],"schema":{"tableName":"_smrt_report_schedules","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_schedules\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"cron\\" TEXT NOT NULL,\\n \\"trigger\\" TEXT NOT NULL,\\n \\"mode\\" TEXT NOT NULL,\\n \\"enabled\\" BOOLEAN NOT NULL,\\n \\"status\\" TEXT NOT NULL,\\n \\"next_run\\" TIMESTAMP,\\n \\"last_run\\" TIMESTAMP,\\n \\"last_status\\" TEXT,\\n \\"last_error\\" TEXT,\\n \\"run_count\\" INTEGER NOT NULL,\\n \\"success_count\\" INTEGER NOT NULL,\\n \\"failure_count\\" INTEGER NOT NULL,\\n \\"running_count\\" INTEGER NOT NULL,\\n \\"max_concurrent\\" INTEGER NOT NULL,\\n \\"queue\\" TEXT NOT NULL,\\n \\"priority\\" INTEGER NOT NULL,\\n \\"timeout\\" INTEGER NOT NULL\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"cron":{"type":"TEXT","notNull":true,"unique":false},"trigger":{"type":"TEXT","notNull":true,"unique":false},"mode":{"type":"TEXT","notNull":true,"unique":false},"enabled":{"type":"BOOLEAN","notNull":true,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"next_run":{"type":"TIMESTAMP","notNull":false,"unique":false},"last_run":{"type":"TIMESTAMP","notNull":false,"unique":false},"last_status":{"type":"TEXT","notNull":false,"unique":false},"last_error":{"type":"TEXT","notNull":false,"unique":false},"run_count":{"type":"INTEGER","notNull":true,"unique":false},"success_count":{"type":"INTEGER","notNull":true,"unique":false},"failure_count":{"type":"INTEGER","notNull":true,"unique":false},"running_count":{"type":"INTEGER","notNull":true,"unique":false},"max_concurrent":{"type":"INTEGER","notNull":true,"unique":false},"queue":{"type":"TEXT","notNull":true,"unique":false},"priority":{"type":"INTEGER","notNull":true,"unique":false},"timeout":{"type":"INTEGER","notNull":true,"unique":false}},"indexes":[{"name":"_smrt_report_schedules_report_class_scope_key_idx","columns":["report_class","scope_key","cron","mode"],"unique":true},{"name":"_smrt_report_schedules_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_schedules_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"4b9f0e69"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportScheduleCollection":{"name":"smrtreportschedulecollection","className":"SmrtReportScheduleCollection","qualifiedName":"@happyvertical/smrt-reports:SmrtReportScheduleCollection","collection":"smrtreportschedules","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_schedules","api":false,"mcp":false,"cli":{"include":["list","get"],"skipApiCheck":true}},"extends":"SmrtCollection","extendsTypeArg":"SmrtReportSchedule","exportName":"SmrtReportScheduleCollection","collectionExportName":"SmrtReportScheduleCollectionCollection","schema":{"tableName":"_smrt_report_schedules","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_schedules\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"cron\\" TEXT NOT NULL,\\n \\"trigger\\" TEXT NOT NULL,\\n \\"mode\\" TEXT NOT NULL,\\n \\"enabled\\" BOOLEAN NOT NULL,\\n \\"status\\" TEXT NOT NULL,\\n \\"next_run\\" TIMESTAMP,\\n \\"last_run\\" TIMESTAMP,\\n \\"last_status\\" TEXT,\\n \\"last_error\\" TEXT,\\n \\"run_count\\" INTEGER NOT NULL,\\n \\"success_count\\" INTEGER NOT NULL,\\n \\"failure_count\\" INTEGER NOT NULL,\\n \\"running_count\\" INTEGER NOT NULL,\\n \\"max_concurrent\\" INTEGER NOT NULL,\\n \\"queue\\" TEXT NOT NULL,\\n \\"priority\\" INTEGER NOT NULL,\\n \\"timeout\\" INTEGER NOT NULL\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"cron":{"type":"TEXT","notNull":true,"unique":false},"trigger":{"type":"TEXT","notNull":true,"unique":false},"mode":{"type":"TEXT","notNull":true,"unique":false},"enabled":{"type":"BOOLEAN","notNull":true,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"next_run":{"type":"TIMESTAMP","notNull":false,"unique":false},"last_run":{"type":"TIMESTAMP","notNull":false,"unique":false},"last_status":{"type":"TEXT","notNull":false,"unique":false},"last_error":{"type":"TEXT","notNull":false,"unique":false},"run_count":{"type":"INTEGER","notNull":true,"unique":false},"success_count":{"type":"INTEGER","notNull":true,"unique":false},"failure_count":{"type":"INTEGER","notNull":true,"unique":false},"running_count":{"type":"INTEGER","notNull":true,"unique":false},"max_concurrent":{"type":"INTEGER","notNull":true,"unique":false},"queue":{"type":"TEXT","notNull":true,"unique":false},"priority":{"type":"INTEGER","notNull":true,"unique":false},"timeout":{"type":"INTEGER","notNull":true,"unique":false}},"indexes":[{"name":"_smrt_report_schedules_report_class_scope_key_idx","columns":["report_class","scope_key","cron","mode"],"unique":true},{"name":"_smrt_report_schedules_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_schedules_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"4b9f0e69"},"importPath":"@happyvertical/smrt-reports/state"}},"moduleType":"smrt","recipes":[{"id":"reports.materialized","className":"MaterializedReportsRecipe","label":"Scheduled reports","summary":"Keep totals and trends ready to read, refreshed on a schedule and open to the assistant.","synonyms":["rollups","kpis","refresh schedule","materialized"],"models":["@happyvertical/smrt-reports:SmrtReportRun","@happyvertical/smrt-reports:SmrtReportWatermark","@happyvertical/smrt-reports:SmrtReportLock","@happyvertical/smrt-reports:SmrtReportSchedule","@happyvertical/smrt-reports:SmrtReportRefreshTask","@happyvertical/smrt-reports:SmrtPrincipalReportRefreshTask"],"nav":[],"requires":[],"help":{"markdown":"## Overview\\n\\nReports keep totals and trends, such as revenue by month or signups by week,\\nworked out ahead of time so they open instantly. Someone on your team sets up\\neach report once. This feature then records when each report was last\\nrefreshed, how that went, and when it runs next.\\n\\nReports are calculated on your server, never in the browser, so this feature\\nneeds your app's database.\\n\\n## Tasks\\n\\n### Ask the assistant about a report\\n\\n1. Ask in plain words, for example \\"what was revenue last month?\\".\\n2. The assistant looks up the reports your account may see\\n (\`data.discover\`, \`data.inspect\`), then reads rows with \`reports.query\`.\\n It only ever sees the columns and the customer data you are allowed to see.\\n3. If the numbers look old, ask how fresh the report is. The answer says when\\n it was last refreshed.\\n4. Ask the assistant to refresh a stale report. It previews the refresh with\\n \`reports.refresh\` and your app decides who may apply it.\\n\\nThe assistant offers these tools only when your app has switched them on.\\n\\n### Ask a question no report covers\\n\\n1. Describe what you want to see, for example \\"orders by status this quarter\\".\\n2. The assistant checks what it may report on (\`reports.runtime.sources\`) and\\n shows a preview of the report it would save (\`reports.runtime.define\`).\\n3. Nothing is saved until you confirm that exact report.\\n4. Open it again later with \`reports.runtime.list\` and \`reports.runtime.run\`.\\n\\nThese reports are worked out live each time and their rows are never stored.\\nThey are not refreshed in the background. A report that people open every day\\nis worth asking your team to set up as a refreshed report instead.\\n\\n### Keep a report fresh\\n\\n1. Ask your team how the report refreshes: by hand, on a schedule, after the\\n data changes, or when it goes out of date.\\n2. A scheduled report repeats on its **{field:SmrtReportSchedule.cron}**, either\\n rebuilding everything or updating only what changed, per its\\n **{field:SmrtReportSchedule.mode}**.\\n3. Turn **{field:SmrtReportSchedule.enabled}** off to pause a schedule without\\n losing it.\\n4. **{field:SmrtReportSchedule.nextRun}** shows when it is next due.\\n\\n### Check that a refresh worked\\n\\n1. Look at the latest run for the report. **{field:SmrtReportRun.status}**\\n says whether it is running, finished, failed or skipped.\\n2. **{field:SmrtReportRun.completedAt}** and **{field:SmrtReportRun.rowCount}**\\n show when it finished and how many rows it holds.\\n3. If it failed, **{field:SmrtReportRun.error}** says why.\\n","fieldRefs":["SmrtReportRun.completedAt","SmrtReportRun.error","SmrtReportRun.rowCount","SmrtReportRun.status","SmrtReportSchedule.cron","SmrtReportSchedule.enabled","SmrtReportSchedule.mode","SmrtReportSchedule.nextRun"]},"runtime":"server","demo":{"mode":"server","reasons":["The recipe declares runtime \\"server\\".","Needs a server because its package does not build for a browser: node:crypto/events; @happyvertical/sql root: the sync query builders it needs (validateColumnName, buildWhere, buildAggregate, bucketExpr, tableExists) have no browser-safe SDK entry; and its package depends on @happyvertical/smrt-jobs, @happyvertical/smrt-tenancy, which do not build for a browser (#3615, #3624, #3625, #3627)."]}},{"id":"reports.runtime","className":"RuntimeReportsRecipe","label":"Reports","summary":"Ask for a report, approve it, and share its live totals with your team.","synonyms":["report","summary","summaries","totals","trends","dashboards"],"models":["@happyvertical/smrt-reports:RuntimeReport"],"nav":[{"label":"Saved reports","model":"@happyvertical/smrt-reports:RuntimeReport","icon":"fileText","description":"Reports your team approved, kept up to date.","noun":"report"}],"requires":[],"help":{"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","fieldRefs":[]},"surfaces":[{"kind":"widget","type":"saved-reports","export":"@happyvertical/smrt-reports/svelte#SavedReportsWidget","label":"Saved reports","description":"Your team\u2019s saved reports with their latest figures.","icon":"fileText","options":[{"key":"limit","type":"integer","label":"Reports shown","default":6,"min":1,"max":24}],"sectionDefault":true,"defaultSpan":4,"minSpan":2,"maxSpan":4},{"kind":"route","path":"/reports","export":"@happyvertical/smrt-reports/svelte#RuntimeReportsRoute","label":"Reports"},{"kind":"route","path":"/reports/:id","export":"@happyvertical/smrt-reports/svelte#RuntimeReportDetailRoute","label":"Report detail"},{"kind":"widget","type":"runtime-report-chart","export":"@happyvertical/smrt-reports/svelte#RuntimeReportChartWidget","label":"Report chart","description":"Chart a measure from a saved report.","icon":"chart","optionsEditor":"@happyvertical/smrt-reports/svelte#RuntimeReportWidgetOptions","options":[{"key":"reportId","type":"text","label":"Report","required":true},{"key":"measure","type":"identifier","label":"Measure","required":true},{"key":"dimension","type":"identifier","label":"Dimension"}],"data":{"load":"@happyvertical/smrt-reports#loadRuntimeReportChart","models":["@happyvertical/smrt-reports:RuntimeReport"]},"defaultSpan":2,"maxSpan":4}],"runtime":"server","demo":{"mode":"server","reasons":["The recipe declares runtime \\"server\\".","Needs a server because its package does not build for a browser: node:crypto/events; @happyvertical/sql root: the sync query builders it needs (validateColumnName, buildWhere, buildAggregate, bucketExpr, tableExists) have no browser-safe SDK entry; and its package depends on @happyvertical/smrt-jobs, @happyvertical/smrt-tenancy, which do not build for a browser (#3615, #3624, #3625, #3627)."]}}],"smrtDependencies":["@happyvertical/smrt-core","@happyvertical/smrt-jobs","@happyvertical/smrt-tenancy"],"browser":{"status":"server-only","issues":["#3615","#3624","#3625","#3627"],"reason":"node:crypto/events; @happyvertical/sql root: the sync query builders it needs (validateColumnName, buildWhere, buildAggregate, bucketExpr, tableExists) have no browser-safe SDK entry","via":["@happyvertical/smrt-jobs","@happyvertical/smrt-tenancy"]},"stampsConstructors":true}`));
|
|
4
|
+
ObjectRegistry.registerPackageManifest(JSON.parse(`{"version":"1.0.0","timestamp":0,"packageName":"@happyvertical/smrt-reports","packageVersion":"0.57.33","objects":{"@happyvertical/smrt-reports:SmrtReport":{"name":"smrtreport","className":"SmrtReport","qualifiedName":"@happyvertical/smrt-reports:SmrtReport","collection":"smrtreports","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/report.ts","packageName":"@happyvertical/smrt-reports","fields":{"refreshedAt":{"type":"datetime","required":false}},"methods":{"isStale":{"name":"isStale","async":false,"parameters":[{"name":"ttlMs","type":"number","optional":true}],"returnType":"boolean","isStatic":false,"isPublic":true},"refresh":{"name":"refresh","async":true,"parameters":[{"name":"options","type":"Omit<ReportRefreshOptions, 'db'>","optional":true}],"returnType":"Promise<ReportRefreshResult>","isStatic":false,"isPublic":true}},"decoratorConfig":{},"extends":"SmrtObject","exportName":"SmrtReport","collectionExportName":"SmrtReportCollection","importPath":"@happyvertical/smrt-reports"},"@happyvertical/smrt-reports:SmrtReportCollection":{"name":"smrtreportcollection","className":"SmrtReportCollection","qualifiedName":"@happyvertical/smrt-reports:SmrtReportCollection","collection":"smrtreports","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/report.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{"refresh":{"name":"refresh","async":true,"parameters":[{"name":"options","type":"Omit<ReportRefreshOptions, 'db'>","optional":true}],"returnType":"Promise<ReportRefreshResult>","isStatic":false,"isPublic":true},"list":{"name":"list","async":true,"parameters":[{"name":"options","type":"SmrtListOptions<ModelType>","optional":true}],"returnType":"Promise<SmrtObject[] | Record<string, unknown>[]>","isStatic":false,"isPublic":true},"get":{"name":"get","async":true,"parameters":[{"name":"filter","type":"any","optional":false,"typeUnresolved":true},{"name":"options","type":"any","optional":true,"typeUnresolved":true}],"returnType":"Promise<ModelType | null>","isStatic":false,"isPublic":true}},"decoratorConfig":{},"extends":"SmrtCollection","extendsTypeArg":"ModelType","exportName":"SmrtReportCollection","collectionExportName":"SmrtReportCollectionCollection","importPath":"@happyvertical/smrt-reports"},"@happyvertical/smrt-reports:RuntimeReport":{"name":"runtimereport","className":"RuntimeReport","qualifiedName":"@happyvertical/smrt-reports:RuntimeReport","collection":"runtimereports","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/runtime-report.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"title":{"type":"text","required":false,"_meta":{}},"description":{"type":"text","required":false,"_meta":{}},"sourceId":{"type":"text","required":false,"_meta":{}},"spec":{"type":"text","required":true,"_meta":{"required":true}},"specHash":{"type":"text","required":false,"_meta":{}},"status":{"type":"text","required":true,"_meta":{"required":true},"enum":["active","archived"]},"createdByUserId":{"type":"text","required":false,"_meta":{}}},"methods":{"run":{"name":"run","async":true,"parameters":[],"returnType":"Promise<RuntimeReportResult>","isStatic":false,"isPublic":true},"archive":{"name":"archive","async":true,"parameters":[{"name":"options","type":"object","optional":false,"memberTypes":["boolean"]}],"returnType":"Promise<object>","isStatic":false,"isPublic":true},"getSpec":{"name":"getSpec","async":false,"parameters":[],"returnType":"RuntimeReportSpec","isStatic":false,"isPublic":true},"setSpec":{"name":"setSpec","async":false,"parameters":[{"name":"spec","type":"RuntimeReportSpec","optional":false}],"returnType":"void","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"runtime_reports","indexes":[{"name":"idx_runtime_reports_confirm","columns":["tenantId","createdByUserId","specHash","status"]}],"operationPermissions":{"run":{"action":"read"},"archive":{"action":"create","databaseActions":["SELECT","UPDATE"]}},"api":{"include":["list","get","create","run","archive"],"principalContext":true,"routes":{"run":{"method":"POST","scope":"item","effect":"read","idempotent":true,"openWorld":false},"archive":{"method":"POST","scope":"item","effect":"write","idempotent":true,"openWorld":false}}},"mcp":{"include":["list","get","run","archive"]},"cli":{"include":["list","get","run","archive"]},"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"RuntimeReport","collectionExportName":"RuntimeReportCollection","displayLabelField":"title","validationRules":[{"field":"spec","rule":"required","fieldType":"text"},{"field":"status","rule":"required","fieldType":"text"}],"schema":{"tableName":"runtime_reports","ddl":"CREATE TABLE IF NOT EXISTS \\"runtime_reports\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"title\\" TEXT,\\n \\"description\\" TEXT,\\n \\"source_id\\" TEXT,\\n \\"spec\\" TEXT NOT NULL,\\n \\"spec_hash\\" TEXT,\\n \\"status\\" TEXT NOT NULL,\\n \\"created_by_user_id\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"title":{"type":"TEXT","notNull":false,"unique":false},"description":{"type":"TEXT","notNull":false,"unique":false},"source_id":{"type":"TEXT","notNull":false,"unique":false},"spec":{"type":"TEXT","notNull":true,"unique":false},"spec_hash":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"created_by_user_id":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"runtime_reports_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"idx_runtime_reports_confirm","columns":["tenant_id","created_by_user_id","spec_hash","status"]},{"name":"runtime_reports_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"04a92513"},"importPath":"@happyvertical/smrt-reports"},"@happyvertical/smrt-reports:RuntimeReportCollection":{"name":"runtimereportcollection","className":"RuntimeReportCollection","qualifiedName":"@happyvertical/smrt-reports:RuntimeReportCollection","collection":"runtimereports","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/runtime-report.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{},"decoratorConfig":{"tableName":"runtime_reports","api":{"include":["list","get","create"]},"mcp":{"include":["list","get"]},"cli":{"include":["list","get"]}},"extends":"SmrtCollection","extendsTypeArg":"RuntimeReport","exportName":"RuntimeReportCollection","collectionExportName":"RuntimeReportCollectionCollection","schema":{"tableName":"runtime_reports","ddl":"CREATE TABLE IF NOT EXISTS \\"runtime_reports\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"title\\" TEXT,\\n \\"description\\" TEXT,\\n \\"source_id\\" TEXT,\\n \\"spec\\" TEXT NOT NULL,\\n \\"spec_hash\\" TEXT,\\n \\"status\\" TEXT NOT NULL,\\n \\"created_by_user_id\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"title":{"type":"TEXT","notNull":false,"unique":false},"description":{"type":"TEXT","notNull":false,"unique":false},"source_id":{"type":"TEXT","notNull":false,"unique":false},"spec":{"type":"TEXT","notNull":true,"unique":false},"spec_hash":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"created_by_user_id":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"runtime_reports_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"idx_runtime_reports_confirm","columns":["tenant_id","created_by_user_id","spec_hash","status"]},{"name":"runtime_reports_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"04a92513"},"importPath":"@happyvertical/smrt-reports"},"@happyvertical/smrt-reports:SmrtReportRefreshTask":{"name":"smrtreportrefreshtask","className":"SmrtReportRefreshTask","qualifiedName":"@happyvertical/smrt-reports:SmrtReportRefreshTask","collection":"smrtreportrefreshtasks","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/scheduler.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"reportClass":{"type":"text","required":true,"_meta":{"required":true}},"mode":{"type":"text","required":true,"_meta":{"required":true},"enum":["rebuild","incremental"]},"trigger":{"type":"text","required":true,"_meta":{"required":true},"enum":["manual","schedule","change","ttl","job"]},"args":{"type":"json","required":false,"_meta":{}}},"methods":{"run":{"name":"run","async":true,"parameters":[{"name":"args","type":"ReportRefreshJobArgs","optional":true},{"name":"context","type":"JobExecutionContext","optional":true}],"returnType":"Promise<unknown>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"_smrt_report_refresh_tasks","api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"SmrtReportRefreshTask","collectionExportName":"SmrtReportRefreshTaskCollection","validationRules":[{"field":"reportClass","rule":"required","fieldType":"text"},{"field":"mode","rule":"required","fieldType":"text"},{"field":"trigger","rule":"required","fieldType":"text"}],"schema":{"tableName":"_smrt_report_refresh_tasks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_refresh_tasks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"mode\\" TEXT NOT NULL,\\n \\"trigger\\" TEXT NOT NULL,\\n \\"args\\" JSON\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"mode":{"type":"TEXT","notNull":true,"unique":false},"trigger":{"type":"TEXT","notNull":true,"unique":false},"args":{"type":"JSON","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_refresh_tasks_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"_smrt_report_refresh_tasks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"c9142042"},"importPath":"@happyvertical/smrt-reports/scheduler"},"@happyvertical/smrt-reports:SmrtPrincipalReportRefreshTask":{"name":"smrtprincipalreportrefreshtask","className":"SmrtPrincipalReportRefreshTask","qualifiedName":"@happyvertical/smrt-reports:SmrtPrincipalReportRefreshTask","collection":"smrtprincipalreportrefreshtasks","description":"Worker target whose authority requirement cannot be downgraded by job args.","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/scheduler.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"generated":true,"source":"tenantScoped_decorator","sqlType":"UUID","__tenancy":{"isTenantIdField":true,"mode":"optional","field":"tenantId","autoFilter":true,"autoPopulate":true,"allowSuperAdminBypass":false}}}},"methods":{"run":{"name":"run","async":true,"parameters":[{"name":"args","type":"ReportRefreshJobArgs","optional":true},{"name":"context","type":"JobExecutionContext","optional":true}],"returnType":"Promise<unknown>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"_smrt_principal_report_refresh_tasks","api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtReportRefreshTask","exportName":"SmrtPrincipalReportRefreshTask","collectionExportName":"SmrtPrincipalReportRefreshTaskCollection","schema":{"tableName":"_smrt_principal_report_refresh_tasks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_principal_report_refresh_tasks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_principal_report_refresh_tasks_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"_smrt_principal_report_refresh_tasks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"226a3b97"},"importPath":"@happyvertical/smrt-reports/scheduler"},"@happyvertical/smrt-reports:SmrtReportRun":{"name":"smrtreportrun","className":"SmrtReportRun","qualifiedName":"@happyvertical/smrt-reports:SmrtReportRun","collection":"smrtreportruns","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"scopeKey":{"type":"text","required":true,"_meta":{"required":true}},"reportClass":{"type":"text","required":true,"_meta":{"required":true}},"sourceClass":{"type":"text","required":true,"_meta":{"required":true}},"mode":{"type":"text","required":true,"_meta":{"required":true},"enum":["rebuild","incremental"]},"trigger":{"type":"text","required":true,"_meta":{"required":true},"enum":["manual","schedule","change","ttl","job"]},"status":{"type":"text","required":true,"description":"Whether the refresh is running, finished, failed or was skipped.","_meta":{"required":true,"description":"Whether the refresh is running, finished, failed or was skipped."},"enum":["running","success","failed","skipped"]},"startedAt":{"type":"datetime","required":true,"description":"When the refresh began.","_meta":{"required":true,"description":"When the refresh began."}},"completedAt":{"type":"datetime","required":false,"description":"When the refresh finished. Empty while it is still running.","_meta":{"nullable":true,"description":"When the refresh finished. Empty while it is still running."}},"rowCount":{"type":"integer","required":true,"description":"How many rows the report held after the refresh.","_meta":{"required":true,"description":"How many rows the report held after the refresh."}},"changedGroupCount":{"type":"integer","required":true,"_meta":{"required":true}},"watermarkBefore":{"type":"text","required":false,"_meta":{"nullable":true}},"watermarkAfter":{"type":"text","required":false,"_meta":{"nullable":true}},"error":{"type":"text","required":false,"description":"Why the refresh failed. Empty when it worked.","_meta":{"nullable":true,"description":"Why the refresh failed. Empty when it worked."}},"metadata":{"type":"json","required":false,"_meta":{}}},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_runs","api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"SmrtReportRun","collectionExportName":"SmrtReportRunCollection","validationRules":[{"field":"scopeKey","rule":"required","fieldType":"text"},{"field":"reportClass","rule":"required","fieldType":"text"},{"field":"sourceClass","rule":"required","fieldType":"text"},{"field":"mode","rule":"required","fieldType":"text"},{"field":"trigger","rule":"required","fieldType":"text"},{"field":"status","rule":"required","fieldType":"text"},{"field":"startedAt","rule":"required","fieldType":"datetime"},{"field":"rowCount","rule":"required","fieldType":"integer"},{"field":"changedGroupCount","rule":"required","fieldType":"integer"}],"schema":{"tableName":"_smrt_report_runs","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_runs\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"source_class\\" TEXT NOT NULL,\\n \\"mode\\" TEXT NOT NULL,\\n \\"trigger\\" TEXT NOT NULL,\\n \\"status\\" TEXT NOT NULL,\\n \\"started_at\\" TIMESTAMP NOT NULL,\\n \\"completed_at\\" TIMESTAMP,\\n \\"row_count\\" INTEGER NOT NULL,\\n \\"changed_group_count\\" INTEGER NOT NULL,\\n \\"watermark_before\\" TEXT,\\n \\"watermark_after\\" TEXT,\\n \\"error\\" TEXT,\\n \\"metadata\\" JSON\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"source_class":{"type":"TEXT","notNull":true,"unique":false},"mode":{"type":"TEXT","notNull":true,"unique":false},"trigger":{"type":"TEXT","notNull":true,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"started_at":{"type":"TIMESTAMP","notNull":true,"unique":false},"completed_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"row_count":{"type":"INTEGER","notNull":true,"unique":false},"changed_group_count":{"type":"INTEGER","notNull":true,"unique":false},"watermark_before":{"type":"TEXT","notNull":false,"unique":false},"watermark_after":{"type":"TEXT","notNull":false,"unique":false},"error":{"type":"TEXT","notNull":false,"unique":false},"metadata":{"type":"JSON","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_runs_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"_smrt_report_runs_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"54ff5048"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportRunCollection":{"name":"smrtreportruncollection","className":"SmrtReportRunCollection","qualifiedName":"@happyvertical/smrt-reports:SmrtReportRunCollection","collection":"smrtreportruns","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_runs","api":false,"mcp":false,"cli":{"include":["list","get"],"skipApiCheck":true}},"extends":"SmrtCollection","extendsTypeArg":"SmrtReportRun","exportName":"SmrtReportRunCollection","collectionExportName":"SmrtReportRunCollectionCollection","schema":{"tableName":"_smrt_report_runs","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_runs\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"source_class\\" TEXT NOT NULL,\\n \\"mode\\" TEXT NOT NULL,\\n \\"trigger\\" TEXT NOT NULL,\\n \\"status\\" TEXT NOT NULL,\\n \\"started_at\\" TIMESTAMP NOT NULL,\\n \\"completed_at\\" TIMESTAMP,\\n \\"row_count\\" INTEGER NOT NULL,\\n \\"changed_group_count\\" INTEGER NOT NULL,\\n \\"watermark_before\\" TEXT,\\n \\"watermark_after\\" TEXT,\\n \\"error\\" TEXT,\\n \\"metadata\\" JSON\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"source_class":{"type":"TEXT","notNull":true,"unique":false},"mode":{"type":"TEXT","notNull":true,"unique":false},"trigger":{"type":"TEXT","notNull":true,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"started_at":{"type":"TIMESTAMP","notNull":true,"unique":false},"completed_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"row_count":{"type":"INTEGER","notNull":true,"unique":false},"changed_group_count":{"type":"INTEGER","notNull":true,"unique":false},"watermark_before":{"type":"TEXT","notNull":false,"unique":false},"watermark_after":{"type":"TEXT","notNull":false,"unique":false},"error":{"type":"TEXT","notNull":false,"unique":false},"metadata":{"type":"JSON","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_runs_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"_smrt_report_runs_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"54ff5048"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportWatermark":{"name":"smrtreportwatermark","className":"SmrtReportWatermark","qualifiedName":"@happyvertical/smrt-reports:SmrtReportWatermark","collection":"smrtreportwatermarks","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"scopeKey":{"type":"text","required":true,"_meta":{"required":true}},"reportClass":{"type":"text","required":true,"_meta":{"required":true}},"sourceClass":{"type":"text","required":true,"_meta":{"required":true}},"watermarkColumn":{"type":"text","required":true,"_meta":{"required":true}},"watermarkValue":{"type":"text","required":false,"_meta":{"nullable":true}},"lastRunId":{"type":"text","required":false,"_meta":{"nullable":true}}},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_watermarks","conflictColumns":["report_class","scope_key","source_class","watermark_column"],"api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"}},"extends":"SmrtObject","exportName":"SmrtReportWatermark","collectionExportName":"SmrtReportWatermarkCollection","validationRules":[{"field":"scopeKey","rule":"required","fieldType":"text"},{"field":"reportClass","rule":"required","fieldType":"text"},{"field":"sourceClass","rule":"required","fieldType":"text"},{"field":"watermarkColumn","rule":"required","fieldType":"text"}],"schema":{"tableName":"_smrt_report_watermarks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_watermarks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"source_class\\" TEXT NOT NULL,\\n \\"watermark_column\\" TEXT NOT NULL,\\n \\"watermark_value\\" TEXT,\\n \\"last_run_id\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"source_class":{"type":"TEXT","notNull":true,"unique":false},"watermark_column":{"type":"TEXT","notNull":true,"unique":false},"watermark_value":{"type":"TEXT","notNull":false,"unique":false},"last_run_id":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_watermarks_report_class_scope_key_idx","columns":["report_class","scope_key","source_class","watermark_column"],"unique":true},{"name":"_smrt_report_watermarks_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_watermarks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"dac9d57a"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportWatermarkCollection":{"name":"smrtreportwatermarkcollection","className":"SmrtReportWatermarkCollection","qualifiedName":"@happyvertical/smrt-reports:SmrtReportWatermarkCollection","collection":"smrtreportwatermarks","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_watermarks","api":false,"mcp":false,"cli":{"include":["list","get"],"skipApiCheck":true}},"extends":"SmrtCollection","extendsTypeArg":"SmrtReportWatermark","exportName":"SmrtReportWatermarkCollection","collectionExportName":"SmrtReportWatermarkCollectionCollection","schema":{"tableName":"_smrt_report_watermarks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_watermarks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"source_class\\" TEXT NOT NULL,\\n \\"watermark_column\\" TEXT NOT NULL,\\n \\"watermark_value\\" TEXT,\\n \\"last_run_id\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"source_class":{"type":"TEXT","notNull":true,"unique":false},"watermark_column":{"type":"TEXT","notNull":true,"unique":false},"watermark_value":{"type":"TEXT","notNull":false,"unique":false},"last_run_id":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_watermarks_report_class_scope_key_idx","columns":["report_class","scope_key","source_class","watermark_column"],"unique":true},{"name":"_smrt_report_watermarks_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_watermarks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"dac9d57a"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportLock":{"name":"smrtreportlock","className":"SmrtReportLock","qualifiedName":"@happyvertical/smrt-reports:SmrtReportLock","collection":"smrtreportlocks","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"scopeKey":{"type":"text","required":true,"_meta":{"required":true}},"reportClass":{"type":"text","required":true,"_meta":{"required":true}},"ownerId":{"type":"text","required":false,"_meta":{"nullable":true}},"acquiredAt":{"type":"datetime","required":false,"_meta":{"nullable":true}},"heartbeatAt":{"type":"datetime","required":false,"_meta":{"nullable":true}},"expiresAt":{"type":"datetime","required":false,"_meta":{"nullable":true}}},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_locks","conflictColumns":["report_class","scope_key"],"api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"}},"extends":"SmrtObject","exportName":"SmrtReportLock","collectionExportName":"SmrtReportLockCollection","validationRules":[{"field":"scopeKey","rule":"required","fieldType":"text"},{"field":"reportClass","rule":"required","fieldType":"text"}],"schema":{"tableName":"_smrt_report_locks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_locks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"owner_id\\" TEXT,\\n \\"acquired_at\\" TIMESTAMP,\\n \\"heartbeat_at\\" TIMESTAMP,\\n \\"expires_at\\" TIMESTAMP\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"owner_id":{"type":"TEXT","notNull":false,"unique":false},"acquired_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"heartbeat_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"expires_at":{"type":"TIMESTAMP","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_locks_report_class_scope_key_idx","columns":["report_class","scope_key"],"unique":true},{"name":"_smrt_report_locks_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_locks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"4a2043f9"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportLockCollection":{"name":"smrtreportlockcollection","className":"SmrtReportLockCollection","qualifiedName":"@happyvertical/smrt-reports:SmrtReportLockCollection","collection":"smrtreportlocks","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_locks","api":false,"mcp":false,"cli":{"include":["list","get"],"skipApiCheck":true}},"extends":"SmrtCollection","extendsTypeArg":"SmrtReportLock","exportName":"SmrtReportLockCollection","collectionExportName":"SmrtReportLockCollectionCollection","schema":{"tableName":"_smrt_report_locks","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_locks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"owner_id\\" TEXT,\\n \\"acquired_at\\" TIMESTAMP,\\n \\"heartbeat_at\\" TIMESTAMP,\\n \\"expires_at\\" TIMESTAMP\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"owner_id":{"type":"TEXT","notNull":false,"unique":false},"acquired_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"heartbeat_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"expires_at":{"type":"TIMESTAMP","notNull":false,"unique":false}},"indexes":[{"name":"_smrt_report_locks_report_class_scope_key_idx","columns":["report_class","scope_key"],"unique":true},{"name":"_smrt_report_locks_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_locks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"4a2043f9"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportSchedule":{"name":"smrtreportschedule","className":"SmrtReportSchedule","qualifiedName":"@happyvertical/smrt-reports:SmrtReportSchedule","collection":"smrtreportschedules","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"scopeKey":{"type":"text","required":true,"_meta":{"required":true}},"reportClass":{"type":"text","required":true,"_meta":{"required":true}},"cron":{"type":"text","required":true,"description":"When the report refreshes, as a cron schedule such as 0 6 * * * for 6 am daily.","_meta":{"required":true,"description":"When the report refreshes, as a cron schedule such as 0 6 * * * for 6 am daily."}},"trigger":{"type":"text","required":true,"_meta":{"required":true},"enum":["manual","schedule","change","ttl","job"]},"mode":{"type":"text","required":true,"description":"Rebuild recomputes the whole report. Incremental updates only what changed.","_meta":{"required":true,"description":"Rebuild recomputes the whole report. Incremental updates only what changed."},"enum":["rebuild","incremental"]},"enabled":{"type":"boolean","required":true,"description":"Turn off to stop refreshing without deleting the schedule.","_meta":{"required":true,"description":"Turn off to stop refreshing without deleting the schedule."}},"status":{"type":"text","required":true,"description":"Whether the schedule is active, paused, disabled or in error.","_meta":{"required":true,"description":"Whether the schedule is active, paused, disabled or in error."},"enum":["active","paused","disabled","error"]},"nextRun":{"type":"datetime","required":false,"description":"When the report is next due to refresh.","_meta":{"nullable":true,"description":"When the report is next due to refresh."}},"lastRun":{"type":"datetime","required":false,"description":"When the report last started a scheduled refresh.","_meta":{"nullable":true,"description":"When the report last started a scheduled refresh."}},"lastStatus":{"type":"text","required":false,"description":"Whether the last scheduled refresh worked or failed.","_meta":{"nullable":true,"description":"Whether the last scheduled refresh worked or failed."},"enum":["success","failed"]},"lastError":{"type":"text","required":false,"description":"Why the last scheduled refresh failed. Empty when it worked.","_meta":{"nullable":true,"description":"Why the last scheduled refresh failed. Empty when it worked."}},"runCount":{"type":"integer","required":true,"_meta":{"required":true}},"successCount":{"type":"integer","required":true,"_meta":{"required":true}},"failureCount":{"type":"integer","required":true,"_meta":{"required":true}},"runningCount":{"type":"integer","required":true,"_meta":{"required":true}},"maxConcurrent":{"type":"integer","required":true,"_meta":{"required":true}},"queue":{"type":"text","required":true,"_meta":{"required":true}},"priority":{"type":"integer","required":true,"_meta":{"required":true}},"timeout":{"type":"integer","required":true,"_meta":{"required":true}}},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_schedules","conflictColumns":["report_class","scope_key","cron","mode"],"api":false,"cli":{"include":["list","get"],"skipApiCheck":true,"http":false},"mcp":false,"tenantScoped":{"mode":"optional"}},"extends":"SmrtObject","exportName":"SmrtReportSchedule","collectionExportName":"SmrtReportScheduleCollection","validationRules":[{"field":"scopeKey","rule":"required","fieldType":"text"},{"field":"reportClass","rule":"required","fieldType":"text"},{"field":"cron","rule":"required","fieldType":"text"},{"field":"trigger","rule":"required","fieldType":"text"},{"field":"mode","rule":"required","fieldType":"text"},{"field":"enabled","rule":"required","fieldType":"boolean"},{"field":"status","rule":"required","fieldType":"text"},{"field":"runCount","rule":"required","fieldType":"integer"},{"field":"successCount","rule":"required","fieldType":"integer"},{"field":"failureCount","rule":"required","fieldType":"integer"},{"field":"runningCount","rule":"required","fieldType":"integer"},{"field":"maxConcurrent","rule":"required","fieldType":"integer"},{"field":"queue","rule":"required","fieldType":"text"},{"field":"priority","rule":"required","fieldType":"integer"},{"field":"timeout","rule":"required","fieldType":"integer"}],"schema":{"tableName":"_smrt_report_schedules","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_schedules\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"cron\\" TEXT NOT NULL,\\n \\"trigger\\" TEXT NOT NULL,\\n \\"mode\\" TEXT NOT NULL,\\n \\"enabled\\" BOOLEAN NOT NULL,\\n \\"status\\" TEXT NOT NULL,\\n \\"next_run\\" TIMESTAMP,\\n \\"last_run\\" TIMESTAMP,\\n \\"last_status\\" TEXT,\\n \\"last_error\\" TEXT,\\n \\"run_count\\" INTEGER NOT NULL,\\n \\"success_count\\" INTEGER NOT NULL,\\n \\"failure_count\\" INTEGER NOT NULL,\\n \\"running_count\\" INTEGER NOT NULL,\\n \\"max_concurrent\\" INTEGER NOT NULL,\\n \\"queue\\" TEXT NOT NULL,\\n \\"priority\\" INTEGER NOT NULL,\\n \\"timeout\\" INTEGER NOT NULL\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"cron":{"type":"TEXT","notNull":true,"unique":false},"trigger":{"type":"TEXT","notNull":true,"unique":false},"mode":{"type":"TEXT","notNull":true,"unique":false},"enabled":{"type":"BOOLEAN","notNull":true,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"next_run":{"type":"TIMESTAMP","notNull":false,"unique":false},"last_run":{"type":"TIMESTAMP","notNull":false,"unique":false},"last_status":{"type":"TEXT","notNull":false,"unique":false},"last_error":{"type":"TEXT","notNull":false,"unique":false},"run_count":{"type":"INTEGER","notNull":true,"unique":false},"success_count":{"type":"INTEGER","notNull":true,"unique":false},"failure_count":{"type":"INTEGER","notNull":true,"unique":false},"running_count":{"type":"INTEGER","notNull":true,"unique":false},"max_concurrent":{"type":"INTEGER","notNull":true,"unique":false},"queue":{"type":"TEXT","notNull":true,"unique":false},"priority":{"type":"INTEGER","notNull":true,"unique":false},"timeout":{"type":"INTEGER","notNull":true,"unique":false}},"indexes":[{"name":"_smrt_report_schedules_report_class_scope_key_idx","columns":["report_class","scope_key","cron","mode"],"unique":true},{"name":"_smrt_report_schedules_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_schedules_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"4b9f0e69"},"importPath":"@happyvertical/smrt-reports/state"},"@happyvertical/smrt-reports:SmrtReportScheduleCollection":{"name":"smrtreportschedulecollection","className":"SmrtReportScheduleCollection","qualifiedName":"@happyvertical/smrt-reports:SmrtReportScheduleCollection","collection":"smrtreportschedules","filePath":"/home/runner/work/smrt/smrt/packages/reports/src/state.ts","packageName":"@happyvertical/smrt-reports","fields":{},"methods":{},"decoratorConfig":{"tableName":"_smrt_report_schedules","api":false,"mcp":false,"cli":{"include":["list","get"],"skipApiCheck":true}},"extends":"SmrtCollection","extendsTypeArg":"SmrtReportSchedule","exportName":"SmrtReportScheduleCollection","collectionExportName":"SmrtReportScheduleCollectionCollection","schema":{"tableName":"_smrt_report_schedules","ddl":"CREATE TABLE IF NOT EXISTS \\"_smrt_report_schedules\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"scope_key\\" TEXT NOT NULL,\\n \\"report_class\\" TEXT NOT NULL,\\n \\"cron\\" TEXT NOT NULL,\\n \\"trigger\\" TEXT NOT NULL,\\n \\"mode\\" TEXT NOT NULL,\\n \\"enabled\\" BOOLEAN NOT NULL,\\n \\"status\\" TEXT NOT NULL,\\n \\"next_run\\" TIMESTAMP,\\n \\"last_run\\" TIMESTAMP,\\n \\"last_status\\" TEXT,\\n \\"last_error\\" TEXT,\\n \\"run_count\\" INTEGER NOT NULL,\\n \\"success_count\\" INTEGER NOT NULL,\\n \\"failure_count\\" INTEGER NOT NULL,\\n \\"running_count\\" INTEGER NOT NULL,\\n \\"max_concurrent\\" INTEGER NOT NULL,\\n \\"queue\\" TEXT NOT NULL,\\n \\"priority\\" INTEGER NOT NULL,\\n \\"timeout\\" INTEGER NOT NULL\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"scope_key":{"type":"TEXT","notNull":true,"unique":false},"report_class":{"type":"TEXT","notNull":true,"unique":false},"cron":{"type":"TEXT","notNull":true,"unique":false},"trigger":{"type":"TEXT","notNull":true,"unique":false},"mode":{"type":"TEXT","notNull":true,"unique":false},"enabled":{"type":"BOOLEAN","notNull":true,"unique":false},"status":{"type":"TEXT","notNull":true,"unique":false},"next_run":{"type":"TIMESTAMP","notNull":false,"unique":false},"last_run":{"type":"TIMESTAMP","notNull":false,"unique":false},"last_status":{"type":"TEXT","notNull":false,"unique":false},"last_error":{"type":"TEXT","notNull":false,"unique":false},"run_count":{"type":"INTEGER","notNull":true,"unique":false},"success_count":{"type":"INTEGER","notNull":true,"unique":false},"failure_count":{"type":"INTEGER","notNull":true,"unique":false},"running_count":{"type":"INTEGER","notNull":true,"unique":false},"max_concurrent":{"type":"INTEGER","notNull":true,"unique":false},"queue":{"type":"TEXT","notNull":true,"unique":false},"priority":{"type":"INTEGER","notNull":true,"unique":false},"timeout":{"type":"INTEGER","notNull":true,"unique":false}},"indexes":[{"name":"_smrt_report_schedules_report_class_scope_key_idx","columns":["report_class","scope_key","cron","mode"],"unique":true},{"name":"_smrt_report_schedules_slug_context_idx","columns":["slug","context"]},{"name":"_smrt_report_schedules_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"4b9f0e69"},"importPath":"@happyvertical/smrt-reports/state"}},"moduleType":"smrt","recipes":[{"id":"reports.materialized","className":"MaterializedReportsRecipe","label":"Scheduled reports","summary":"Keep totals and trends ready to read, refreshed on a schedule and open to the assistant.","synonyms":["rollups","kpis","refresh schedule","materialized"],"models":["@happyvertical/smrt-reports:SmrtReportRun","@happyvertical/smrt-reports:SmrtReportWatermark","@happyvertical/smrt-reports:SmrtReportLock","@happyvertical/smrt-reports:SmrtReportSchedule","@happyvertical/smrt-reports:SmrtReportRefreshTask","@happyvertical/smrt-reports:SmrtPrincipalReportRefreshTask"],"nav":[],"requires":[],"help":{"markdown":"## Overview\\n\\nReports keep totals and trends, such as revenue by month or signups by week,\\nworked out ahead of time so they open instantly. Someone on your team sets up\\neach report once. This feature then records when each report was last\\nrefreshed, how that went, and when it runs next.\\n\\nReports are calculated on your server, never in the browser, so this feature\\nneeds your app's database.\\n\\n## Tasks\\n\\n### Ask the assistant about a report\\n\\n1. Ask in plain words, for example \\"what was revenue last month?\\".\\n2. The assistant looks up the reports your account may see\\n (\`data.discover\`, \`data.inspect\`), then reads rows with \`reports.query\`.\\n It only ever sees the columns and the customer data you are allowed to see.\\n3. If the numbers look old, ask how fresh the report is. The answer says when\\n it was last refreshed.\\n4. Ask the assistant to refresh a stale report. It previews the refresh with\\n \`reports.refresh\` and your app decides who may apply it.\\n\\nThe assistant offers these tools only when your app has switched them on.\\n\\n### Ask a question no report covers\\n\\n1. Describe what you want to see, for example \\"orders by status this quarter\\".\\n2. The assistant checks what it may report on (\`reports.runtime.sources\`) and\\n shows a preview of the report it would save (\`reports.runtime.define\`).\\n3. Nothing is saved until you confirm that exact report.\\n4. Open it again later with \`reports.runtime.list\` and \`reports.runtime.run\`.\\n\\nThese reports are worked out live each time and their rows are never stored.\\nThey are not refreshed in the background. A report that people open every day\\nis worth asking your team to set up as a refreshed report instead.\\n\\n### Keep a report fresh\\n\\n1. Ask your team how the report refreshes: by hand, on a schedule, after the\\n data changes, or when it goes out of date.\\n2. A scheduled report repeats on its **{field:SmrtReportSchedule.cron}**, either\\n rebuilding everything or updating only what changed, per its\\n **{field:SmrtReportSchedule.mode}**.\\n3. Turn **{field:SmrtReportSchedule.enabled}** off to pause a schedule without\\n losing it.\\n4. **{field:SmrtReportSchedule.nextRun}** shows when it is next due.\\n\\n### Check that a refresh worked\\n\\n1. Look at the latest run for the report. **{field:SmrtReportRun.status}**\\n says whether it is running, finished, failed or skipped.\\n2. **{field:SmrtReportRun.completedAt}** and **{field:SmrtReportRun.rowCount}**\\n show when it finished and how many rows it holds.\\n3. If it failed, **{field:SmrtReportRun.error}** says why.\\n","fieldRefs":["SmrtReportRun.completedAt","SmrtReportRun.error","SmrtReportRun.rowCount","SmrtReportRun.status","SmrtReportSchedule.cron","SmrtReportSchedule.enabled","SmrtReportSchedule.mode","SmrtReportSchedule.nextRun"]},"runtime":"server","demo":{"mode":"server","reasons":["The recipe declares runtime \\"server\\".","Needs a server because its package does not build for a browser: node:crypto/events; @happyvertical/sql root: the sync query builders it needs (validateColumnName, buildWhere, buildAggregate, bucketExpr, tableExists) have no browser-safe SDK entry; and its package depends on @happyvertical/smrt-jobs, @happyvertical/smrt-tenancy, which do not build for a browser (#3615, #3624, #3625, #3627)."]}},{"id":"reports.runtime","className":"RuntimeReportsRecipe","label":"Reports","summary":"Ask for a report, approve it, and share its live totals with your team.","synonyms":["report","summary","summaries","totals","trends","dashboards"],"models":["@happyvertical/smrt-reports:RuntimeReport"],"nav":[{"label":"Saved reports","model":"@happyvertical/smrt-reports:RuntimeReport","icon":"fileText","description":"Reports your team approved, kept up to date.","noun":"report"}],"requires":[],"help":{"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","fieldRefs":[]},"surfaces":[{"kind":"widget","type":"saved-reports","export":"@happyvertical/smrt-reports/svelte#SavedReportsWidget","label":"Saved reports","description":"Your team\u2019s saved reports with their latest figures.","icon":"fileText","options":[{"key":"limit","type":"integer","label":"Reports shown","default":6,"min":1,"max":24}],"sectionDefault":true,"defaultSpan":4,"minSpan":2,"maxSpan":4},{"kind":"route","path":"/reports","export":"@happyvertical/smrt-reports/svelte#RuntimeReportsRoute","label":"Reports"},{"kind":"route","path":"/reports/:id","export":"@happyvertical/smrt-reports/svelte#RuntimeReportDetailRoute","label":"Report detail"},{"kind":"widget","type":"runtime-report-chart","export":"@happyvertical/smrt-reports/svelte#RuntimeReportChartWidget","label":"Report chart","description":"Chart a measure from a saved report.","icon":"chart","optionsEditor":"@happyvertical/smrt-reports/svelte#RuntimeReportWidgetOptions","options":[{"key":"reportId","type":"text","label":"Report","required":true},{"key":"measure","type":"identifier","label":"Measure","required":true},{"key":"dimension","type":"identifier","label":"Dimension"}],"data":{"load":"@happyvertical/smrt-reports#loadRuntimeReportChart","models":["@happyvertical/smrt-reports:RuntimeReport"]},"defaultSpan":2,"maxSpan":4}],"runtime":"server","demo":{"mode":"server","reasons":["The recipe declares runtime \\"server\\".","Needs a server because its package does not build for a browser: node:crypto/events; @happyvertical/sql root: the sync query builders it needs (validateColumnName, buildWhere, buildAggregate, bucketExpr, tableExists) have no browser-safe SDK entry; and its package depends on @happyvertical/smrt-jobs, @happyvertical/smrt-tenancy, which do not build for a browser (#3615, #3624, #3625, #3627)."]}}],"smrtDependencies":["@happyvertical/smrt-core","@happyvertical/smrt-jobs","@happyvertical/smrt-tenancy"],"browser":{"status":"server-only","issues":["#3615","#3624","#3625","#3627"],"reason":"node:crypto/events; @happyvertical/sql root: the sync query builders it needs (validateColumnName, buildWhere, buildAggregate, bucketExpr, tableExists) have no browser-safe SDK entry","via":["@happyvertical/smrt-jobs","@happyvertical/smrt-tenancy"]},"stampsConstructors":true}`));
|
|
5
5
|
//#endregion
|
|
6
6
|
//#region src/state.ts
|
|
7
7
|
var __defProp = Object.defineProperty;
|