Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .changeset/prune-report-aria-performance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
"@objectstack/spec": minor
---

feat(spec)!: prune the dead `aria` / `performance` props from ReportSchema (report-liveness close-out)

Follow-up to the #3463 report cleanup. The 2026-06 ReportSchema liveness audit
flagged `aria` and `performance` as dead — declared on `ReportSchema` (and
editable in the Studio report form) but read by **no renderer**. This removes
them. Every other finding from that audit is now closed too: `chart` turned out
to be **live** (`DatasetReportRenderer` plots `chart.xAxis`/`yAxis` via
`DatasetReportChart`), and the obsolete sub-schemas / naming-drift / joined-preview
items were resolved by #3463 and earlier work.

- Removed `ReportSchema.aria` (`AriaPropsSchema`) and `ReportSchema.performance`
(`PerformanceConfigSchema`), dropping the now-orphan imports. Both schemas
remain exported and are still used by other metadata types (views, pages,
charts) — only the report's use of them is removed. `ReportChart` keeps its
own `aria` (inherited from `ChartConfigSchema`).
- No manifest key or public export changes (`aria`/`performance` were properties,
not schemas); `report.mdx` regenerated.

**Migration**: nothing an author writes changes — no first-party or example
report set `aria`/`performance`. Reports carry no ARIA/performance overrides;
use the dataset/view surface for those concerns. Ships as `minor` per the
launch-window breaking-as-minor policy.
2 changes: 0 additions & 2 deletions content/docs/references/ui/report.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ const result = JoinedReportBlock.parse(data);
| **runtimeFilter** | `any` | optional | Render-time scope filter |
| **drilldown** | `boolean` | ✅ | Click-through to underlying records |
| **chart** | `{ type: Enum<'bar' \| 'horizontal-bar' \| 'column' \| 'line' \| 'area' \| 'pie' \| 'donut' \| 'funnel' \| 'scatter' \| 'treemap' \| 'sankey' \| 'gauge' \| 'solid-gauge' \| 'metric' \| 'kpi' \| 'bullet' \| 'radar' \| 'table' \| 'pivot'>; title?: string; subtitle?: string; description?: string; … }` | optional | Embedded chart configuration |
| **aria** | `{ ariaLabel?: string; ariaDescribedBy?: string; role?: string }` | optional | ARIA accessibility attributes |
| **performance** | `{ lazyLoad?: boolean; virtualScroll?: object; cacheStrategy?: Enum<'none' \| 'cache-first' \| 'network-first' \| 'stale-while-revalidate'>; prefetch?: boolean; … }` | optional | Performance optimization settings |
| **blocks** | `{ name: string; label?: string; description?: string; type: Enum<'tabular' \| 'summary' \| 'matrix'>; … }[]` | optional | Sub-reports for type=joined |
| **protection** | `{ lock: Enum<'none' \| 'no-overlay' \| 'no-delete' \| 'full'>; reason: string; docsUrl?: string }` | optional | Package author protection block — lock policy for this report. |
| **_lock** | `Enum<'none' \| 'no-overlay' \| 'no-delete' \| 'full'>` | optional | Item-level lock — controls overlay & delete (ADR-0010). |
Expand Down
7 changes: 7 additions & 0 deletions docs/audits/2026-06-reportschema-property-liveness.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

**Date**: 2026-06-15 · **Scope**: `packages/spec/src/ui/report.zod.ts` (ADR-0021 single-form). **Live path**: `objectui` `ReportRenderer`→`DatasetReportRenderer` (dataset-bound). Pre-9.0 object/columns-query renderers retired; old JSON limps through the lossy `specReportToPresentation` bridge.

> **✅ Fully resolved — 2026-07-25** (#3463 + follow-up). Every finding below has since been actioned; the dated body is kept as the point-in-time snapshot.
> - **`chart` — WIRED, not dead.** `DatasetReportRenderer` now plots `report.chart.xAxis`/`yAxis` over the bound dataset via `DatasetReportChart` (`DatasetReportRenderer.tsx:429-465,773-786`); #3441 corrected the `.describe()`, and the showcase gained a `chart`-bearing report (`showcase_hours_by_status_chart`) so the path is dogfooded.
> - **`aria`, `performance` — PRUNED** from `ReportSchema` (2026-07 report-liveness close-out).
> - **`ReportColumnSchema` / `ReportGroupingSchema` (+ objectui `SpecReportColumn*`/`SpecReportGrouping*` re-exports) — REMOVED** (#3463 → framework #3488 / objectui #2816).
> - **`ReportChartSchema` naming drift — RESOLVED**: the legacy `ReportViewer` chart branch that read `xAxisField`/`yAxisFields` was retired (objectui #2816); the live renderer reads the spec's `xAxis`/`yAxis`; the unread `groupBy` was pruned (#3488).
> - **Studio joined preview — FIXED**: `ReportPreview` branches on `dataset || blocks` (`isJoinedWithBlocks`).

## LIVE & well-wired (dataset shape — the canonical path)
`name`, `label`, `description`, `type` (summary/tabular/matrix/joined), `dataset`, `rows`, `columns` (matrix-across only, matches spec), `values`, `runtimeFilter` (`?? filter`, ANDed via `mergeFilters`), `drilldown` (default-on; cells clickable), `blocks` (joined, per-block dataset/rows/columns/values/runtimeFilter). Evidence: `DatasetReportRenderer.tsx:486-575`, `:493-543`. Wired types: tabular/summary/matrix (true cross-tab + server totals + drill)/joined.

Expand Down
4 changes: 3 additions & 1 deletion docs/audits/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ The most serious cluster — properties that imply a security boundary but enfor
- **Role `parent`** / **SharingRuleSchema** — manager rollup & spec sharing rules disconnected from the live engine.

### 2. 🔴 ADR-0021 analytics migration debt
Spec moved to `dataset`+`values`/`dimensions`, but: the **chart view variant** + **dashboard renderer + Studio WidgetConfigPanel** still read the *removed* legacy `object/valueField/categoryField/aggregate` shape; **report `chart`** is dead; `ReportColumn`/`ReportGrouping` are obsolete re-exports. (Same debt that invalidated the showcase dashboard/report seeds.)
Spec moved to `dataset`+`values`/`dimensions`, but: the **chart view variant** + **dashboard renderer + Studio WidgetConfigPanel** still read the *removed* legacy `object/valueField/categoryField/aggregate` shape. (Same debt that invalidated the showcase dashboard/report seeds.)

**✅ Report slice resolved (#3463 + 2026-07 close-out).** `report.chart` is **wired** (`DatasetReportRenderer` plots `chart.xAxis`/`yAxis` via `DatasetReportChart`, now dogfooded by the showcase `…_chart` report); `ReportColumn`/`ReportGrouping` (+ objectui `SpecReport*` re-exports) and the unread `chart.groupBy` + dead `aria`/`performance` are **removed**; the legacy `ReportViewer` chart fallback is **retired**. See [`2026-06-reportschema-property-liveness.md`](./2026-06-reportschema-property-liveness.md). The **chart-view / dashboard / WidgetConfigPanel** legacy-shape readers above remain open.

### 3. 🟠 Naming drift → silent no-ops (spec key ≠ consumed key)
field `maxLength`/`minLength`/`referenceFilters`/`maxRating`; page `type`→`pageType` & `label`→`title` & `visibility`; dashboard `title` vs `label`; app `accentColor`/`badgeVariant`/`separator` (renderer reads, **not in spec**); action `disabled`→`enabled`; flow `http` vs `http_request`; skill `requiredPermissions` vs `permissions`; agent `knowledge.{topics→sources}`; webhook `object`→`object_name`, `isActive`→`active`.
Expand Down
1 change: 1 addition & 0 deletions examples/app-showcase/src/ui/apps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export const ShowcaseApp = App.create({
{ id: 'nav_charts', type: 'dashboard', dashboardName: 'showcase_chart_gallery', label: 'Chart Gallery', icon: 'layout-dashboard' },
{ id: 'nav_report_tabular', type: 'object', objectName: 'showcase_task', viewName: 'tabular', label: 'Task List', icon: 'table' },
{ id: 'nav_report_summary', type: 'report', reportName: 'showcase_hours_by_status', label: 'Hours by Status', icon: 'sigma' },
{ id: 'nav_report_chart', type: 'report', reportName: 'showcase_hours_by_status_chart', label: 'Hours by Status (Chart)', icon: 'bar-chart-3' },
{ id: 'nav_report_matrix', type: 'report', reportName: 'showcase_status_priority_matrix', label: 'Status × Priority', icon: 'grid-3x3' },
{ id: 'nav_report_joined', type: 'report', reportName: 'showcase_task_overview', label: 'Task Overview', icon: 'layers' },
],
Expand Down
21 changes: 21 additions & 0 deletions examples/app-showcase/src/ui/reports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,29 @@ export const TaskOverviewReport = defineReport({
],
});

/** 5 ── Summary with an embedded chart. Exercises the live `DatasetReportChart`
* path: `chart.xAxis`/`yAxis` name the bound dataset's dimension/measure and
* are plotted via a second `queryDataset` call (ADR-0021). */
export const HoursByStatusChartReport = defineReport({
name: 'showcase_hours_by_status_chart',
label: 'Hours by Status (Chart)',
description: 'Estimated hours by status, plotted as a bar chart.',
type: 'summary',
drilldown: true,
dataset: 'showcase_task_metrics',
rows: ['status'],
values: ['est_hours'],
chart: {
// Chart type from ChartConfig; xAxis = dataset dimension, yAxis = measure.
type: 'bar',
xAxis: 'status',
yAxis: 'est_hours',
},
});

export const allReports = [
HoursByStatusReport,
StatusPriorityMatrixReport,
TaskOverviewReport,
HoursByStatusChartReport,
];
6 changes: 3 additions & 3 deletions examples/app-showcase/test/seed.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ describe('showcase stack', () => {
expect((stack.views ?? []).length).toBeGreaterThan(0);
expect((stack.dashboards ?? []).length).toBeGreaterThan(0);
// ADR-0021 single-form: the former flat `tabular` TaskListReport was
// reclassified as a ListView (a flat list is a row lens, not analytics),
// leaving 3 dataset-bound analytics reports.
expect((stack.reports ?? []).length).toBe(3);
// reclassified as a ListView (a flat list is a row lens, not analytics).
// Four dataset-bound analytics reports: summary, chart, matrix, joined.
expect((stack.reports ?? []).length).toBe(4);
expect((stack.flows ?? []).length).toBeGreaterThan(0);
// Nine flat positions (contributor/manager/exec/auditor/ops/
// field_ops_delegate/client_portal_user, plus finance/legal for the v16
Expand Down
9 changes: 1 addition & 8 deletions packages/spec/src/ui/report.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import { MetadataProtectionFields } from '../kernel/metadata-protection.zod';
import { FilterConditionSchema } from '../data/filter.zod';
import { ChartConfigSchema } from './chart.zod';
import { SnakeCaseIdentifierSchema } from '../shared/identifiers.zod';
import { I18nLabelSchema, AriaPropsSchema } from './i18n.zod';
import { PerformanceConfigSchema } from './responsive.zod';
import { I18nLabelSchema } from './i18n.zod';

/**
* Report Type Enum
Expand Down Expand Up @@ -126,12 +125,6 @@ export const ReportSchema = lazySchema(() => z.object({
/** Visualization */
chart: ReportChartSchema.optional().describe('Embedded chart configuration'),

/** ARIA accessibility attributes */
aria: AriaPropsSchema.optional().describe('ARIA accessibility attributes'),

/** Performance optimization settings */
performance: PerformanceConfigSchema.optional().describe('Performance optimization settings'),

/**
* Joined report blocks — only meaningful when `type: 'joined'`.
*
Expand Down