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
- Open a workspace with at least one custom field created via Settings → Data Model UI (i.e. not from an app's manifest).
- Open Settings → Data Model → select any custom field on a standard or custom object.
- 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.
- 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.
Description
In Settings → Data Model UI, custom fields are listed by label, type, and status (active/inactive), but the originating
applicationIdis not visible in the UI. The field'sapplicationIdexists on the underlyingfieldMetadatarow 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
applicationIdis non-null.fieldMetadatafiltering byapplicationId, or (b)psqlinto the database and join againstcore.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 ifapplicationIdpoints 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
fieldMetadata.applicationIdin the Settings → Data Model UI — both in the field list and the field detail view.name(e.g. "es-oie", "PM Command Center") when it maps to a knowncore.applicationrow.applicationIdis the catch-all Custom bucket (i.e. the app name is literallyCustomandsourceType = localwithsourcePath = 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.core.applicationrow (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
projectobject survivedapp:uninstalland 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
Out of scope for this issue (callouts, not requests)
app:uninstallto 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.applicationIdalready exists onfieldMetadata; the only change is rendering it.Happy to provide
applicationIdcould look.