Skip to main content
Media is an atomic, reusable binary-asset record that stores logos, avatars, and banners for companies and people in the Well platform. Each row carries a media_type enum, an optional human label, and the GCS asset location expressed either as a legacy url (deprecated) or a modern GCS path (preferred). Media rows are workspace-scoped via a nullable ManyToOne to Workspace. CompanyMedia and PersonMedia are independent pivot entities that each hold a ManyToOne reference to Media — the Media entity itself declares no back-reference collections.

API operations

Data model

Attributes

Relationships

System-computed

  • media_id: generated by PostgreSQL gen_random_uuid() at INSERT time via @Property({ defaultRaw: 'gen_random_uuid()' }). Never set by application code.
  • created_at: initialized to new Date() as a TypeScript class field default AND set by MikroORM onCreate: () => new Date() lifecycle hook. Always populated.
  • updated_at: set by MikroORM onCreate and onUpdate lifecycle hooks. No TypeScript default initializer — the field is updated_at?: Date (optional). NULL on records that have never been updated after initial creation.
  • deleted_at: soft-delete sentinel. NULL = active. Application must never issue hard DELETEs against the media table; set deleted_at = NOW() instead.
  • URL resolution: the public-facing url attribute in the JSON:API response is NOT the raw media.url column. The formatter calls resolveMediaUrl(media) which returns buildMediaCdnUrl(media.path) when path is present, and falls back to media.url otherwise. Consumers must never read media.url or media.path directly — always use the resolved url from the formatted response.
  • Workspace scoping: added retroactively by Migration20260105120000. Existing unscoped media was reassigned to workspaces via a data migration that de-duplicated assets shared across multiple workspaces by inserting new media rows per workspace.
  • Deprecated url column: the url column was originally NOT NULL (see Migration20250919154301 DDL). It was later made nullable by the GCS migration; all new records store the asset in GCS and leave url NULL.
  • Composite records-table field composite_media_list: built from company_media.media.media_id, company_media.media.label, and company_media.media.media_type (for companies) and the analogous person_media.* paths (for people). Defined in composites.yml; rendered by the records table as a media-list composite cell.
  • Primary media computed field: the PostgreSQL function core_api.company_primary_media(company_row, hasura_session) selects the most-recently-created non-deleted CompanyMedia row for a company and returns a JSONB projection including media_id, media_type, label, url, and path. The function was updated by Migration20260527120000 to include path alongside the legacy url so the data-views layer can derive a CDN URL for logos stored in GCS.
  • Pivot relationships: CompanyMedia and PersonMedia each declare a @ManyToOne to Media on their own entity classes. The Media entity itself declares NO @OneToMany back-references — navigation from Media to its pivot rows is done via Hasura array relationships (metadata-level), not via MikroORM collections.

Example

Source: apps/api/src/database/entities/Media.ts · domain: financial-graph · tier: Supporting