Collect

A Collect represents a single data-collection run initiated by an authenticated user, typically driven by the browser extension (popup, side panel, or blueprint automation). Each run is bound to one People (the subject being enriched), one Workspace (stamped at creation from req.workspace and never re-derived), and optionally one Task (the automation trigger). The status lifecycle progresses from todo through in_progress to finalized or error. Workspace binding is nullable on legacy rows to handle orphaned people records; all workspace-scoped queries silently exclude those rows via Hasura RLS.

NamingValue
ObjectCollect
Resource type (JSON:API type)collect
Collection / records rootโ€” (not a records root)
REST base/v1/collects
Entity classCollect

Internal object. Not currently exposed on the public REST API. The operations below describe the intended contract.

API operations

OperationMethod & pathStatus
ListGET /v1/collects๐ŸŸก Planned
RetrieveGET /v1/collects/{id}๐ŸŸก Planned
CreatePOST /v1/collects๐ŸŸก Planned
UpdatePATCH /v1/collects/{id}๐ŸŸก Planned
DeleteDELETE /v1/collects/{id}๐ŸŸก Planned

Data model

Attributes

FieldTypeRequiredConstraintsAllowed valuesDescription
collect_idstring (UUID)โœ… Yesuniqueโ€”Public stable identifier for the collect run. Generated server-side via gen_random_uuid(); never user-supplied.
providerstringโšช Novarchar(255), nullableโ€”Slug identifying the data-collection provider or browser extension surface that initiated the run (e.g. 'linkedin', 'popup'). Null for manual or legacy rows.
statusenum (collect_status_enum)โœ… Yesnative enum collect_status_enum, default 'todo'todo | in_progress | finalized | errorLifecycle state of the collection run. Defaults to 'todo' at creation; transitions to 'in_progress', then 'finalized' (success) or 'error' (terminal failure). Terminal statuses trigger a workspace_connector_sync_logs entry.
started_at๐Ÿ”’ system โ€” timestamptzโšช Nonullable, timestamptzโ€”Timestamp when the run began active processing. Set by the client via PATCH; null until the extension begins extraction.
ended_at๐Ÿ”’ system โ€” timestamptzโšช Nonullable, timestamptzโ€”Timestamp when the run reached a terminal state (finalized or error). Set by the client via PATCH alongside status update.
created_at๐Ÿ”’ system โ€” timestamptzโœ… Yesnot null, set once on insertโ€”Row creation timestamp. Set via onCreate hook; never user-editable.
updated_at๐Ÿ”’ system โ€” timestamptzโšช Nonullable, set on insert and every updateโ€”Last modification timestamp. Automatically set on every update via onUpdate hook.
deleted_at๐Ÿ”’ system โ€” timestamptzโšช Nonullableโ€”Soft-delete timestamp. When set, the row is excluded from all workspace-scoped queries and Hasura RLS filters. Set via DELETE endpoint (CollectService.deleteCollect).

Relationships

NameTypeRequiredDescription
peopleto-one (ManyToOne)โœ… YesThe People record being enriched during this collection run. Resolved at creation from the authenticated user's associated person. FK: collects.people_pk โ†’ peoples.pk. Indexed via idx_collects_people (partial, deleted_at IS NULL).
workspaceto-one (ManyToOne)โšช No (nullable; required on all new rows by service-layer enforcement)The Workspace this collect run belongs to. Stamped once at creation from req.workspace and never re-derived from subsequent JWT calls, ensuring cross-workspace switches cannot reroute writes mid-flight. Nullable to absorb legacy orphan rows; all workspace-scoped queries (Hasura RLS, service layer) exclude null rows automatically. FK: collects.workspace_pk โ†’ workspaces.pk (cascade update+delete). Indexed via idx_collects_workspace_status.
taskto-one (ManyToOne)โšช NoOptional link to the Task that triggered this collection run (blueprint automation). Null for manual/popup/side-panel collections and legacy rows. FK: collects.task_pk โ†’ tasks.pk. On Task deletion the FK is set to null (deleteRule: 'set null').

System-computed

  • collect_id โ€” generated server-side via gen_random_uuid() defaultRaw; never accepted from client input
  • created_at โ€” set once on insert via MikroORM onCreate hook (new Date())
  • updated_at โ€” refreshed on every update via onUpdate hook (new Date())
  • deleted_at โ€” soft-delete; set to current timestamp by CollectService.deleteCollect; null on active rows
  • workspace (workspace_pk) โ€” stamped at creation time from req.workspace by CollectService.createCollect and never subsequently overwritten, even on PATCH calls; this immutability is the tenant-safety guarantee for in-flight runs
  • status default โ€” CollectStatusEnum.TODO at row creation unless overridden by the POST body
  • idx_collects_status โ€” partial index on status WHERE deleted_at IS NULL
  • idx_collects_people โ€” partial index on people_pk WHERE deleted_at IS NULL
  • idx_collects_workspace_status โ€” composite index on (workspace_pk, status) for active-run queries

Example

{
  "data": {
    "type": "collect",
    "id": "a3f7c2e1-84b0-4d9e-9c12-1e8f7a3b5d22",
    "attributes": {
      "collect_id": "a3f7c2e1-84b0-4d9e-9c12-1e8f7a3b5d22",
      "provider": "linkedin",
      "status": "in_progress",
      "started_at": "2026-06-02T09:15:00.000Z",
      "ended_at": null,
      "created_at": "2026-06-02T09:14:58.123Z",
      "updated_at": "2026-06-02T09:15:01.450Z",
      "deleted_at": null
    },
    "relationships": {
      "people": {
        "data": { "type": "people", "id": "d8b1a4f2-11cc-4e77-b933-abc123456789" }
      },
      "workspace": {
        "data": { "type": "workspace", "id": "7e91cd02-0a3b-4f55-8811-fedcba987654" }
      },
      "task": {
        "data": null
      }
    }
  }
}
Source: /Users/maximechampoux/platform/apps/api/src/database/entities/Collect.ts ยท domain: ingestion ยท tier: Infrastructure