Skip to content

fix(frontend): reject null payloads in dashboard type predicates#6443

Open
eugenegujing wants to merge 3 commits into
apache:mainfrom
eugenegujing:fix/type-predicates-null-guard
Open

fix(frontend): reject null payloads in dashboard type predicates#6443
eugenegujing wants to merge 3 commits into
apache:mainfrom
eugenegujing:fix/type-predicates-null-guard

Conversation

@eugenegujing

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

The five type guards in dashboard/type/type-predicates.ts checked their nested payload with typeof value.<field> === "object", which also accepts null because typeof null === "object" in JavaScript, so an entry like {workflow: null} passed isDashboardWorkflow and the DashboardEntry constructor then crashed with an unrelated TypeError: Cannot read properties of null while dereferencing the payload, instead of reaching its intentional "Unexpected type in DashboardEntry." error path. The guards also returned the falsy input itself rather than false for null/undefined input, violating their declared boolean type-guard signatures.

This PR adds an isNonNullObject type guard (typeof x === "object" && x !== null) to the shared predicate utility (common/util/predicate.ts, next to isDefined) so the correct non-null object check is discoverable and reusable, uses it in the four object-payload guards, and switches all five guards to !!value && ... so they return strict booleans in every path. isDashboardProject's !value.workflow exclusion is deliberately unchanged: a null workflow field means "no workflow data", so an object with a string name still classifies as a project and no valid entry changes classification.

Any related issues, documentation, discussions?

Fixes #6439. The buggy behavior was pinned by the five "(current behavior)" tests added in #6425 (issue #6400), which this PR flips to assert the corrected behavior.

How was this PR tested?

Added predicate.spec.ts (8 tests) covering isNonNullObject and the previously untested isDefined. Updated type-predicates.spec.ts: the four null-payload pins now assert toBe(false), the null/undefined input cases are tightened from toBeFalsy() to toBe(false), and the isDashboardProject null-workflow case keeps asserting true with a comment marking it as an intentional decision; the 5x5 cross-classification matrix and all of its 25 expected values are untouched, confirming that classification of realistic entries is unaffected. Ran locally via yarn ng test --watch=false --include='**/common/util/predicate.spec.ts' --include='**/dashboard/type/type-predicates.spec.ts' (61/61 pass), plus the full frontend suite whose failure set is identical to the unmodified main baseline (pre-existing, environment-related failures only), and tsc --noEmit with zero errors.

Was this PR authored or co-authored using generative AI tooling?

Co-authored using Claude Code(Fable 5).

Add an `isNonNullObject` guard to `common/util/predicate.ts` (with a new predicate.spec.ts, which also covers the previously untested `isDefined`), use it in the four object-payload guards, and switch all five guards to `!!value` so they always return strict booleans. `isDashboardProject`'s `!value.workflow` exclusion is deliberately unchanged. Spec updated: the four "(current behavior)" null-payload pins now assert false; the 5x5 cross-classification matrix and its 25 expected values are untouched, so no realistic entry changes classification.

Fixes apache#6439
@github-actions github-actions Bot added fix frontend Changes related to the frontend GUI labels Jul 15, 2026
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • Contributors with relevant context: @Ma77Ball, @aglinxinyuan, @gracecluvohio
    You can notify them by mentioning @Ma77Ball, @aglinxinyuan, @gracecluvohio in a comment.

@codecov-commenter

codecov-commenter commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.66%. Comparing base (0467c76) to head (51da5ec).

Additional details and impacted files
@@            Coverage Diff            @@
##               main    #6443   +/-   ##
=========================================
  Coverage     74.65%   74.66%           
  Complexity     3438     3438           
=========================================
  Files          1160     1160           
  Lines         45793    45795    +2     
  Branches       5069     5070    +1     
=========================================
+ Hits          34189    34191    +2     
  Misses         9953     9953           
  Partials       1651     1651           
Flag Coverage Δ *Carryforward flag
access-control-service 70.00% <ø> (ø) Carriedforward from 0467c76
agent-service 76.76% <ø> (ø) Carriedforward from 0467c76
amber 66.81% <ø> (ø) Carriedforward from 0467c76
computing-unit-managing-service 18.00% <ø> (ø) Carriedforward from 0467c76
config-service 66.66% <ø> (ø) Carriedforward from 0467c76
file-service 66.80% <ø> (ø) Carriedforward from 0467c76
frontend 78.57% <100.00%> (+<0.01%) ⬆️
notebook-migration-service 78.94% <ø> (ø) Carriedforward from 0467c76
pyamber 91.99% <ø> (ø) Carriedforward from 0467c76
workflow-compiling-service 55.14% <ø> (ø) Carriedforward from 0467c76

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@xuang7 xuang7 added the release/v1.2 back porting to release/v1.2 label Jul 16, 2026
@eugenegujing

Copy link
Copy Markdown
Contributor Author

/request-review @aglinxinyuan

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a correctness gap in the frontend dashboard entry type guards by ensuring nested “payload” fields are rejected when they are null (avoiding the JavaScript typeof null === "object" trap) and by making the guards return strict booleans for null/undefined inputs. This prevents invalid dashboard entries from being misclassified and crashing DashboardEntry construction with unrelated TypeErrors.

Changes:

  • Add a shared isNonNullObject predicate utility and unit tests for it (and for the previously-untested isDefined).
  • Update dashboard type predicates to use isNonNullObject for nested object payload checks and !!value to return strict booleans.
  • Update dashboard predicate unit tests to assert the corrected null-handling behavior while keeping the cross-classification matrix unchanged.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
frontend/src/app/dashboard/type/type-predicates.ts Switch nested payload checks to isNonNullObject and ensure strict-boolean returns.
frontend/src/app/dashboard/type/type-predicates.spec.ts Flip the “current behavior” null-payload pins to assert corrected false results; tighten null/undefined expectations to false.
frontend/src/app/common/util/predicate.ts Introduce reusable isNonNullObject helper alongside isDefined.
frontend/src/app/common/util/predicate.spec.ts Add focused unit tests for isNonNullObject and isDefined.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread frontend/src/app/common/util/predicate.ts
eugenegujing and others added 2 commits July 20, 2026 16:33
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-null-guard

# Conflicts:
#	frontend/src/app/common/util/predicate.spec.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix frontend Changes related to the frontend GUI release/v1.2 back porting to release/v1.2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard type predicates accept null nested fields (typeof null === "object"), letting invalid entries crash DashboardEntry construction

4 participants