> For the complete documentation index, see [llms.txt](https://docs.opendatadiscovery.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opendatadiscovery.org/features/data-discovery/entity-description.md).

# Entity description

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`](/configuration-and-deployment/enable-security/authorization/permissions.md) 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](/features/data-discovery/search.md) result rows.
* The Recommended-tile cards on the [Catalog Overview](/features/data-discovery/catalog-overview.md) home page.
* The [Directory](/features/data-discovery/directory.md)'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](/features/data-discovery/tagging.md) and the [Business Glossary](/features/data-glossary/business-glossary.md) 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:

| Permission                                                                                                     | What it gates                                                                                       |
| -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| [`DATA_ENTITY_DESCRIPTION_UPDATE`](/configuration-and-deployment/enable-security/authorization/permissions.md) | 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](/configuration-and-deployment/enable-security/authorization/permissions.md) 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](/features/active-platform-features/activity-feed.md). 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.

{% hint style="danger" %}
**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.
{% endhint %}

| Surface                                                                            | Canonical home                                                             | Authoring path                                                                         |
| ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| Entity description                                                                 | this page                                                                  | `PUT /api/dataentities/{id}/description`                                               |
| Dataset field (column) description                                                 | [Per-column annotation](/features/data-discovery/per-column-annotation.md) | `PUT /api/datasetfields/{id}/description`                                              |
| Business glossary term definition                                                  | [Business Glossary](/features/data-glossary/business-glossary.md)          | `POST /api/terms` / `PUT /api/terms/{id}`                                              |
| Query Example `definition` + `query`                                               | [Query Examples](/features/data-modelling/query-examples.md)               | `POST /api/queryexample`                                                               |
| Lookup Table cell values + column names + table name                               | [Lookup Tables](/features/master-data-management/lookup-tables.md)         | `POST /api/referencedata/table/{id}/data`                                              |
| Slack-notification body (alert chunk descriptions rendered through Slack `mrkdwn`) | [Notifications](/features/active-platform-features/notifications.md)       | `POST /ingestion/alert/alertmanager` (the inbound webhook embeds description verbatim) |

## Where to next

* [Data entity detail page](/features/data-discovery/entity-detail-page.md) — the per-entity surface where the description renders alongside the schema, lineage, tags, and terms panels.
* [Per-column annotation](/features/data-discovery/per-column-annotation.md) — the column-level counterpart with the same authoring + rendering pipeline (and the same security caveat).
* [Business Glossary](/features/data-glossary/business-glossary.md) — term definitions, the `[[Namespace:Term]]` auto-link target, and the term-mention side-channel.
* [Custom metadata](/features/data-discovery/custom-metadata.md) — operator-curated metadata field catalogue and per-entity value assignments; a sibling per-entity surface on the Overview tab.
* [Manual Object Tagging](/features/data-discovery/tagging.md) — the lightweight labelling counterpart for cross-cutting groupings.
* [Permissions → DATA\_ENTITY\_DESCRIPTION\_UPDATE](/configuration-and-deployment/enable-security/authorization/permissions.md) — the canonical permission row for the Edit affordance.
* [Activity Feed → DESCRIPTION\_UPDATED](/features/active-platform-features/activity-feed.md#event-types) — the audit-feed event emitted on every description edit.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.opendatadiscovery.org/features/data-discovery/entity-description.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
