| media_id | string, UUID, 🔒 system | ✅ Yes | unique; default gen_random_uuid() | — | Public identifier for the media asset. Generated by PostgreSQL on insert via gen_random_uuid(). This is the value exposed in the JSON:API id field. |
| media_type | string (enum) | ✅ Yes | NOT NULL; native PG enum media_type_enum in core_api schema | avatar, logo, banner | Category of the binary asset. avatar is used for person profile pictures; logo for company brand marks; banner for wide header images. Controls how the asset is rendered by cell components in the records table. |
| label | string | ⚪ No | varchar(255) by MikroORM default, nullable | — | Human-readable label for the asset, e.g. “Acme Corp primary logo” or “Profile photo – Q1 2026”. Optional free-text annotation; not used programmatically. |
| url | string | ⚪ No | text, nullable; DEPRECATED — NULL for all assets stored after the GCS migration | — | Legacy absolute URL to the asset. Kept for backward compatibility with records created before the GCS storage migration. For all new assets this column is NULL; the asset is stored at path instead. The formatter’s resolveMediaUrl() falls through to this field only when path is absent. |
| path | string | ⚪ No | text, nullable | — | GCS object path for the asset, e.g. workspaces/<workspace_id>/media/<media_id>.png. The API formatter (resolveMediaUrl() in media.formatter.ts) converts this path to a CDN URL via buildMediaCdnUrl(). Takes priority over the legacy url field when both are present. NULL on pre-migration records. |
| created_at | Date, 🔒 system | ✅ Yes | timestamptz NOT NULL; initialized to new Date() as TypeScript default and also set by MikroORM onCreate lifecycle hook | — | Timestamp when the media record was created. Immutable after insert. |
| updated_at | Date, 🔒 system | ⚪ No | timestamptz, nullable; set by MikroORM onCreate hook on insert AND onUpdate hook on every subsequent write; no TypeScript default initializer (unlike created_at) | — | Timestamp of the last attribute update on this record. Set automatically by MikroORM on both create and update operations. |
| deleted_at | Date | ⚪ No | timestamptz, nullable; NULL = active record | — | Soft-delete timestamp. When non-NULL the record is considered logically deleted. All queries must filter deleted_at IS NULL. The composite index idx_media_workspace_deleted on (workspace_pk, deleted_at) is the hot path for Hasura permission filters. |