Follow-up: lift dashboard container/tile invariants into shared schema

Open
#2,225 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Refactor
Clarity
Mostly clear
Activity status
Quiet
Tech stack
typescript

Research direction

Start with the existing refinement in packages/api/src/routers/external-api/v2/utils/dashboards.ts:706-803 and DashboardSchema in packages/common-utils/src/types.ts:923-1015; scan production Mongo state for invalid references before tightening validation. Done means both schemas use shared container and tile-reference invariants, duplicated API logic is removed, and the tile metadata path is shared by the translators in packages/api/src/utils/externalApi.ts:188-211.

Written by the indexing model from the issue text.

Description

Follow-up to #2201 (compound-engineering-review).

The external dashboards API (packages/api/src/routers/external-api/v2/utils/dashboards.ts, buildDashboardBodySchema) enforces four invariants in a superRefine at the boundary:

  • Container id uniqueness across the dashboard
  • Tab id uniqueness within each container
  • tile.containerId resolves to a real container
  • tile.tabId requires tile.containerId and resolves to a tab in that container

These rules currently live only at the external API. Internal writers (MCP server, hyperdx_save_dashboard, future endpoints) all go through DashboardSchema in packages/common-utils/src/types.ts, which only enforces container-id uniqueness. A non-API writer can persist a dashboard whose tile references a missing container or tab, and the GET endpoint will then re-emit the broken state.

PR #2201 narrowed the gap by tightening containerId/tabId to z.string().min(1).optional() and adding .max() bounds, but it stopped short of moving the cross-reference invariants because that was scope-creep against the API PR.

Proposed fix:

  1. Extract a addDashboardContainerInvariantsIssues(data, ctx) helper into packages/common-utils/src/types.ts (alongside the existing addDuplicateTileIdIssues).
  2. Call it from DashboardSchema.superRefine so internal callers are validated.
  3. Drop the duplicated body inside buildDashboardBodySchema's superRefine and call the same helper.

Risk to address as part of the work:

  • Existing Mongo docs may have invalid state. A migration or read-time normalization may be needed if any dashboards in production violate the invariants. Worth scanning before tightening.

Companion task (also from compound review on #2201): extract applyCommonTileFields(internal, external) for tile-shell metadata so convertToExternalTileChartConfig (new format) and translateExternalChartToTileConfig (legacy series format) both share the metadata-passthrough path. Today both translators duplicate containerId/tabId propagation and the next tile-shell field will too.

References:

  • packages/api/src/routers/external-api/v2/utils/dashboards.ts:706-803 (current refine site)
  • packages/common-utils/src/types.ts:923-1015 (target site)
  • packages/api/src/utils/externalApi.ts:188-211 (legacy translator)
Dominant language
TypeScript
Stars
9.9k
Forks
471
Avg merge
2d 4h
Merged PRs (30d)
117

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from hyperdxio/hyperdx

All issues in hyperdxio/hyperdx

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.