Skip to content

Settings → Data Model UI does not expose which app owns a custom field, making orphaned fields hard to identify #23882

Description

@es-dustinbamberger

Description

In Settings → Data Model UI, custom fields are listed by label, type, and status (active/inactive), but the originating applicationId is not visible in the UI. The field's applicationId exists on the underlying fieldMetadata row and is exposed via the metadata GraphQL API, but the UI doesn't render it.

This makes it hard for workspace admins to answer: "Is this custom field managed by an installed app, or is it an orphan from a previous install/uninstall, a hand-edit, or an earlier version of an app?" — questions that come up routinely during schema audits, before/after uninstall operations, and when investigating field-level bugs.

Reproduction

  1. Open a workspace with at least one custom field created via Settings → Data Model UI (i.e. not from an app's manifest).
  2. Open Settings → Data Model → select any custom field on a standard or custom object.
  3. Inspect the field's detail view — there is no indicator of which application (if any) "owns" this field, even when the underlying applicationId is non-null.
  4. To identify orphan fields today, an operator must either (a) write a custom GraphQL query against fieldMetadata filtering by applicationId, or (b) psql into the database and join against core.application. Neither is something a typical workspace admin will do.

Expected

The field detail view (or the field list row, depending on layout) should show the originating applicationId — rendered as the app name if it resolves to a known application, or as an explicit "no app / custom" badge if applicationId points to the catch-all Custom bucket. The Custom badge is the load-bearing signal: it lets admins scan the model and immediately see which fields are not owned by any installed app.

Suggested fix direction

  • Surface fieldMetadata.applicationId in the Settings → Data Model UI — both in the field list and the field detail view.
  • Resolve it to the application's name (e.g. "es-oie", "PM Command Center") when it maps to a known core.application row.
  • When the applicationId is the catch-all Custom bucket (i.e. the app name is literally Custom and sourceType = local with sourcePath = workspace-custom), show an explicit indicator — e.g. a "Custom / no app" badge or an inline warning — so admins can scan for unattached fields without needing to know about the underlying Custom-bucket mechanism.
  • The same surface should ideally link back to the core.application row (or to the app's uninstall path) so the operator can take action from the field's detail view.

This is a UI/visibility change only. No schema change. No behavior change to install/uninstall/migration logic. No risk of regressing existing workflows.

Why I'm filing this

Hit it during a dev-environment install/uninstall rehearsal for an internal app: 6 custom fields on the standard project object survived app:uninstall and were only identifiable as orphans via a custom GraphQL query. From the UI, they looked identical to fields that were legitimately part of the app — there's no visual signal that they had no managing app. Auditing the workspace state required DB-level access. A workspace admin without GraphQL/DB access would have had no way to even know there was a problem.

Impact

  • Operators cannot audit "which fields are managed by which app" from the UI. They need DB or API access.
  • Orphan fields from past install/uninstall cycles accumulate silently and are only discovered when something breaks (re-install collision, schema-drift investigation, app upgrade pre-check).
  • The catch-all Custom bucket is invisible to admins — there is no UI affordance that distinguishes "field declared by app X's manifest" from "field someone hand-created in Settings."
  • This is a UX gap, not a data-model bug. The metadata is correct on the backend; it just isn't surfaced.

Out of scope for this issue (callouts, not requests)

  • I'm not asking for app:uninstall to change behavior (e.g. start auto-deleting fields it doesn't currently manage). That would be a policy change with real blast radius and reasonable people can disagree on it. Visibility is enough — let admins decide.
  • I'm not asking for new metadata fields. applicationId already exists on fieldMetadata; the only change is rendering it.
  • I'm not asking for changes to the Custom bucket mechanism itself. Whether fields can be hand-created via the UI is a separate question.

Happy to provide

  • A reproducible setup (any app install → uninstall leaves orphans that are only visible via API).
  • Before/after screenshots/mockups of how the surfaced applicationId could look.
  • A reference implementation against the API.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Fields

Priority

None yet

Start date

None yet

Target date

None yet

Dev status

None yet

Quarter

None yet

Projects

Status
In project

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions