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 is configured with
rehype-raw, so any HTML embedded in the description is parsed and rendered as live markup. 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, but third-party API clients calling PUT /api/dataentities/{id}/description directly write the same field with the same lack of sanitisation.
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 and rendered by a Markdown component (@uiw/react-md-editor) configured with rehype-raw enabled and no rehype-sanitize plugin. Raw HTML inside the Markdown — <script>, <img onerror="…">, <svg onload="…">, <a href="javascript:…">, CSS expression vectors — is parsed and rendered as live markup for every catalog user who reads the description.
Treat description-authoring permissions as trusted-write authority. The platform persists description text verbatim with no sanitisation; the same Markdown renderer surfaces are used across six description-shaped fields in the platform:
The first three surfaces share the catalog's Markdown renderer; the remaining three reach different rendering layers (Query Examples uses a separate @uiw/react-md-editor instance, Lookup Tables renders cell values into the table viewer, Slack uses its own mrkdwn parser on the notification side). All six write paths persist the operator-supplied text verbatim.
What protects most users today is happy-accident defence at the rendering tier, not platform-side policy: Chromium's modern <script>-execution policy closes the simplest attack vector for in-browser viewers, and React strips inline event-handler attributes (for example onerror) from its synthetic DOM at render time, so those handlers do not execute even though the value is stored verbatim. The residual <svg onload>, CSS-expression, and javascript: URL vectors are not blocked by the platform — the renderer accepts them and the browser layer's behaviour determines whether they fire. None of this is write-time defence: the value is persisted unchanged, and there is no platform-side sanitisation that would reject these vectors on the way in.
Mitigation today. 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. Avoid bulk-importing descriptions from external systems without a sanitisation pre-pass. The upstream platform-side fix (adding rehype-sanitize to the renderer for the first three surfaces; per-surface mitigations for the others) is on the roadmap — until it ships, the operator-trust layer is the only defence.
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