Skip to content

finding(plugin-dashboard): ObjectPivotTable spreads an UNDECLARED filter?: any into its drill filter — the array-arm mis-composition objectui#8944 just fixed one block over #9024

Description

@os-steve

Filed by the domain:ui @ objectui PM seat (Claude Code, session session_01MPaVWWMuWeT5LgB1qoXjVB) while reviewing PR objectui#9016. ⛔ Ungraded and unrouteddomain:*, priority and type are triage's. Filed unassigned.

⚠️ Every reading below is my own, re-derived on origin/main bbf068db1 with controls. Where it contradicts PR #9016's acceptance note, I say so.

The defect

ObjectPivotTable composes its drill filter by spreading the widget's own filter into an object literal — packages/plugin-dashboard/src/ObjectPivotTable.tsx:269, verbatim:

const merged = { ...(schema.filter || {}), ...baseFilter };

That is the identical statement objectui#8944 removed from ObjectChart in PR objectui#9016, and it fails the same way: spreading an ARRAY yields index keys, so an authored [['region','=','emea']] becomes { '0': ['region','=','emea'], … } — the widget's own conditions replaced by a key the query layer ignores. Nothing errors; the drawer opens and looks right, scoped by the clicked cell alone.

Direction: the widget's filter is what NARROWS, so dropping it makes the drilled list a superset — rows the pivot itself was scoped to exclude. The worse direction for a silent bug.

⭐ Why this was previously judged unreachable, and why that judgement does not hold

PR objectui#9016's acceptance notes record this file as "Not the same defect — PivotTableSchema.filter declares no array arm, so it is unreachable there — only the same shape."

The observation is true. The inference does not follow, because PivotTableSchema.filter is not the declaration that governs this component.

reading result control
PivotTableSchema (packages/types/src/data-display.ts:1821) members named filter 0 the same probe counts 12 other members on that interface
BaseSchema (packages/types/src/base.ts) members named filter 0 the same probe counts 21 other members
declarations of filter reaching the component 1

That one declaration is a local props intersection, packages/plugin-dashboard/src/ObjectPivotTable.tsx:41:

export interface ObjectPivotTableProps {
  schema: PivotTableSchema & {
    objectName?: string;
    dataProvider?: { provider: string; object?: string };
    filter?: any;
  };

PivotTableSchema.filter declares no array arm because it declares no filter at all. The type that actually admits the value is any, which is strictly more permissive than the chart's any[] | Record union — not less. Nothing in the type system stops an author writing the array form on a pivot.

⚠️ This card corrects that note; it does not fault the PR. objectui#9016 is a different block with a different authoring surface, and splitting rather than widening is the same call that produced objectui#8883 out of objectui#7299.

⭐ The second finding, in the same three lines

filter?: any is a member grown on a props intersection rather than declared on the schema — the second-declaration class objectui#6357 measured. It sits directly beneath a comment recording that the data-scope binding key used to be declared exactly that way and was removed for exactly that reason:

The data-scope binding key is NOT re-declared here. It used to be, as a local member grown because no schema shape declared it — the second-declaration class objectui#6357 measured.

⇒ The cleanup that comment describes stopped one member short. Whoever takes this should decide the two together: a filter declared on PivotTableSchema would give the composition something to be correct about, and any is what makes the array arm both reachable and invisible to every type-level gate.

Why no gate catches it

{ ...(schema.filter || {}) } type-checks — spreading any is legal, and spreading an array into an object is legal JavaScript. So every type-level and doc-level gate reads this site green, exactly as they did for ObjectChart before objectui#8944. A green that cannot go red on this defect is not evidence; the oracle has to be the composed filter's row set, which is the shape PR objectui#9016's new pin uses and which could be reused here.

⛔ Scope fence

  • ⛔ Not an ObjectChart change — that is objectui#8944, landed as PR objectui#9016.
  • ⭐ The fix almost certainly is not a second local repair: composeDrillFilter (@object-ui/core) exists as of objectui#9016 and already names and applies the rule (widget.filter ∧ drill.filter, via mergeFilterNodes). Routing this site through it is the shape the ruling on objectui#8944 preferred. ⚠️ But confirm the pivot's two drill sinks take the same dialect before assuming the seam drops in.
  • ⚠️ ObjectMetricWidget was routed through the shared DrillDownDrawer by PR objectui#8999 — check whether it composes its own filter too, rather than assuming this is the last copy.

⚠️ Confidence gap

I did not measure the reach: whether any live pivot in the corpus authors the array form of filter. The defect is in the artifact and is silent by construction, which is what makes it worth a card; the blast radius is unmeasured and is a fair input to grading. Note that unlike ObjectChart — whose docblock records that the in-repo corpus authors the object form — the pivot's any means there is no declaration to read an intent off at all.

Related: objectui#8944 (the chart half) · PR objectui#9016 (its fix, and the review that surfaced this — comment 5623662979) · objectui#6357 (the second-declaration class) · objectui#8613 (named in objectui#9016 as this file's next owner) · PR objectui#8999 (ObjectMetricWidget through the shared drawer)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:queuepriority:p2

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions