Data model

Status: Source-derived from v2/web/src/api.ts types and v2/api/ SELECT/INSERT columns (2026-10-30). Times are Unix milliseconds. IDs are UUIDs unless noted.

Every record below is scoped by tenant_id + workspace_id (+ product where shown); those columns are server-bound and never accepted from a client (Concepts).

Context

Returned by GET /api/v1/context. Note camelCase here versus snake_case elsewhere — a known contract inconsistency (Developer standards).

FieldTypeNotes
principalIdstringactor ID
tenantId, workspaceIdstringscope; workspace mirrors tenant today
tenantNamestringorganization name
rolestringmembership role ([[AUTH
allowedProductsstring[]enabled products
capabilitiesstring[]capability strings
featureRevisionstringentitlement revision
ontologySchemaRevisionstringcurrently "1"
hqlVersionnumbercurrently 1

Event

List/detail/update responses. product ∈ Newsk | Tower | Ops | Civic.

FieldTypeNotes
idUUID
productstringowning product
titlestringsearchable
summarystringsearchable
statusstringnew, reviewing, saved, closed
assigned_tostring/nullself-assignment only
revisionintegeroptimistic-concurrency counter
first_seen_at, last_seen_atnumberms timestamps
latitude, longitudenumber/nullsource-provided only, finite and in range
evidence_countintegercomputed in list queries

Detail adds evidence[] (≤ 100) and activity[] (≤ 50):

Evidence fieldTypeNotes
id, source_idUUID / registered ID
source_urlstringpreserved provenance
publisher, headline, excerptstring
captured_atnumber
artifact_idstring/nullmetadata, not a download URL
Activity fieldTypeNotes
revision, status, assigned_to—state at that revision
changed_bystringactor ID
changed_atnumber

Source and ProductEntitlement

Source fieldTypeNotes
idUUIDapproved, registered sources only
product, publisher, labelstring
enabledbooleanpaused/resumed via PATCH
revisioninteger ≥ 1
created_atnumber

ProductEntitlement: product, enabled, revision (starts 0 before first grant row).

Story and Brief

Story fieldTypeNotes
id, event_idUUIDevent must be Newsk-scoped
titlestring1–240 chars
notesstring≤ 20,000 chars
statusstringdraft, ready, handed_off, archived (no edits after handed_off)
revisioninteger
created_at, updated_atnumber

Brief: id, story_id, title, body (extractive), citations[] (url, publisher, headline, captured_at), generated_by: "extractive", timestamps. GET returns citations_json string — parse it.

OpsAction

FieldTypeNotes
idUUID
source_story_idUUID/nullevent handoffs have none
source_event_idUUID
source_productstringproduct the action came from
story_title, event_titlestringjoined labels
source_url, publisherstring/nulllatest evidence of the event
statusstringopen, in_progress, done, cancelled — transition table in [[API_ENDPOINTS
revisioninteger

Run

FieldTypeNotes
idUUID
source_idUUIDregistered source snapshot taken at dispatch
idempotency_keystring/nullvisible only to runs.manage actors
statusstringqueued, running, succeeded, partial, failed, cancelled
error_codestring/nulle.g. dispatch_unconfirmed
trace_idstringcorrelation for support
created_at, updated_atnumber

Dashboard

FieldTypeNotes
idUUIDowner-only edit/delete
productstringmust be enabled
titlestring1–160 chars
descriptionstring≤ 1,000 chars
config_jsonstringvalidated by shared schema, JSON ≤ 32,000 chars
visibilitystringprivate | workspace
can_editbooleancomputed: caller is owner
revisioninteger

Investigation, InvestigationItem, Entity, Relationship

InvestigationTypeNotes
id, product—
title, summarystringvalidated (invalid_investigation)
statusstringactive, archived
revisioninteger
created_by, created_at, updated_at—
item_countintegeron list
ItemTypeNotes
item_kindstringnote, event, evidence, entity, relationship
titlestring1–240 chars
notestring≤ 5,000 chars
target_event_id, target_evidence_id, target_entity_id, target_relationship_idUUID/nullexactly one target for non-note kinds
EntityTypeNotes
entity_typestringperson, organization, place, asset, public_body, other
display_namestring1–200 chars
descriptionstring≤ 2,000 chars
revisioninteger
RelationshipTypeNotes
from_entity_id, to_entity_idUUIDtwo distinct in-scope entities
relationship_typestring1–80 chars
interpretationstringobserved, inferred, disputed
evidence_idUUIDrequired in-scope evidence
notesstring≤ 2,000 chars

Graph: nodes[] (entity subset) + edges[] (relationships), capped: boolean — treat a capped graph as partial.

WorkspaceSearchResult

type (event, evidence, story, dashboard, action, investigation, entity), id, product, title, description, updated_at, optional event_id / source_product.

See also

  • Concepts — what these records mean.
  • Limits — bounds enforced on each field.
  • API endpoints — where each record is read or written.