Entity description
Operator-authored Markdown description on each data entity — the platform's primary free-text annotation, persisted verbatim and rendered through the same component as terms and columns.
Every data entity in the catalog carries an operator-authored description — free-form Markdown that documents what the entity is for, who reads from it, what the columns mean, and any in-house context that the source system does not carry. The description appears on the entity's detail page as the primary narrative surface above the structural panels (schema, lineage, tags, terms), and it surfaces in search-result rows and the Recommended-tile previews as the first-encounter snippet.
This page covers the authoring workflow, the supported Markdown surface, the permissions that gate editing, the audit trail, and a load-bearing security caveat that applies to six of the platform's free-text Markdown surfaces.
Where to find it
Open any data entity's detail page → Overview tab. The description occupies the top of the Overview body. Operators with the DATA_ENTITY_DESCRIPTION_UPDATE permission see an Edit affordance; readers without the permission see the rendered description and nothing else.
The same description text is also surfaced as the preview snippet on:
Search result rows.
The Recommended-tile cards on the Catalog Overview home page.
The Directory's level-4 entity list rows.
The full Markdown rendering happens on the Overview tab; the preview surfaces above render an abbreviated plain-text projection.
Authoring the description
The Edit affordance opens an inline Markdown editor (@uiw/react-md-editor) with split-pane preview. Operators type the description in Markdown; saving issues PUT /api/dataentities/{id}/description with a JSON body carrying the new description string. The platform persists the text verbatim into the data_entity.internal_description column (PostgreSQL text, no length cap, no transformation other than mapping the empty string to null).
Supported Markdown surface — what the renderer understands and the editor previews:
Headings (
#,##,###, …).Bold, italic, strikethrough.
Inline and fenced code blocks (syntax highlighting on the fenced form via the renderer's highlighter).
Bulleted and numbered lists, including nested lists.
Links —
[text](https://...)plus the auto-link convention[[Namespace:Term]]that resolves to a glossary term (see Manual Object Tagging and the Business Glossary for the term-linking workflow).Tables (GitHub-flavored).
Raw HTML — the renderer parses embedded HTML (
rehype-raw); as of 0.28.0 it then sanitises the parsed HTML (rehype-sanitize) before display, stripping scripts and event-handler /javascript:vectors. See the security caveat below.
The editor is the only place to author the description; there is no API-only path that bypasses the editor's preview. Third-party API clients calling PUT /api/dataentities/{id}/description directly write the same field — the stored value is verbatim either way (HTML sanitisation happens at render time, not on write).
Permissions
Editing the description is gated by one permission:
The Edit affordance on the Overview tab plus the PUT /api/dataentities/{id}/description endpoint.
The permission is bound to the data entity in the URL (per the platform's RBAC model — see Permissions for the full per-resource gating story). Operators without it see the rendered description but no Edit affordance.
Activity trail
Description edits emit a DESCRIPTION_UPDATED event on the Activity Feed. The event carries the entity id, the editor's identity, and the timestamp — and, in its old-state / new-state payload, the full previous description and the full new description. The Activity Feed is therefore a content-diff log for description edits, not merely an audit-of-occurrence: the per-entity Activity tab on the detail page reconstructs both that a description changed and what it changed from and to.
Security caveat — stored-XSS family across six Markdown surfaces
The platform's description-authoring surfaces apply no write-time HTML sanitisation — operator-typed Markdown is persisted verbatim. Rendering is the defence point: as of 0.28.0 the platform's shared Markdown renderer sanitises parsed HTML (rehype-raw → rehype-sanitize) before display, so <script>, <img onerror="…">, <svg onload="…">, <a href="javascript:…">, and CSS-expression vectors embedded in a description are stripped at render time on the surfaces that use that shared renderer (see the table below). Releases up to 0.27.x rendered the parsed HTML as live markup for every reader.
Treat description-authoring permissions as trusted-write authority. The platform persists description text verbatim; the same description-shaped Markdown field appears in six places across the platform:
The first four surfaces — entity description, column description, term definition, and Query Examples (definition + query) — share the catalog's Markdown renderer, and 0.28.0 added render-time HTML sanitisation (rehype-sanitize) to it, closing the embedded-HTML/script vector on those four. The remaining two reach different rendering layers that fix does not cover: Lookup Tables renders cell values into the table viewer, and Slack uses its own mrkdwn parser on the notification side. All six write paths persist the operator-supplied text verbatim.
For the four shared-renderer surfaces the defence is now platform-side: the rehype-sanitize pass added in 0.28.0 strips <script>, inline event-handler attributes (for example onerror), javascript: URLs, and the <svg onload> / CSS-expression vectors before display. For the two remaining surfaces (Lookup Tables, Slack) there is no platform-side sanitisation — they rely on the rendering tier's own behaviour (Chromium's <script>-execution policy, React stripping inline event-handler attributes) plus operator trust, and the residual <svg onload>, CSS-expression, and javascript:-URL vectors are not blocked by the platform on those two paths. Sanitisation everywhere is a render-time defence: the stored value is persisted unchanged on all six write paths.
Mitigation today. The four shared-renderer surfaces are sanitised at render time as of 0.28.0. For the two remaining surfaces (Lookup Tables, Slack) — and as defence-in-depth on every write path — restrict the DATA_ENTITY_DESCRIPTION_UPDATE permission (and its five siblings on the table above) to operators reviewing the source of every value they paste in, the same posture you would apply to any "free-text into the database" surface, and avoid bulk-importing descriptions from external systems without a sanitisation pre-pass.
Entity description
this page
PUT /api/dataentities/{id}/description
Lookup Table cell values + column names + table name
POST /api/referencedata/table/{id}/data
Slack-notification body (alert chunk descriptions rendered through Slack mrkdwn)
POST /ingestion/alert/alertmanager (the inbound webhook embeds description verbatim)
Where to next
Data entity detail page — the per-entity surface where the description renders alongside the schema, lineage, tags, and terms panels.
Per-column annotation — the column-level counterpart with the same authoring + rendering pipeline (and the same security caveat).
Business Glossary — term definitions, the
[[Namespace:Term]]auto-link target, and the term-mention side-channel.Custom metadata — operator-curated metadata field catalogue and per-entity value assignments; a sibling per-entity surface on the Overview tab.
Manual Object Tagging — the lightweight labelling counterpart for cross-cutting groupings.
Permissions → DATA_ENTITY_DESCRIPTION_UPDATE — the canonical permission row for the Edit affordance.
Activity Feed → DESCRIPTION_UPDATED — the audit-feed event emitted on every description edit.
Last updated