An official website of the United States GovernmentUnclassified
Seal of the Department of the NavyDepartment of the NavyProject ROUNDTABLE Docs
Data model

Engagements and notes

The government ledger's record of industry interactions

An engagement records a real interaction between one or more organizations and one command. Examples include a conference discussion, a technical demonstration, a site visit, or a follow-up. It is the ledger's durable answer to “who met whom, when, and why?”

Engagement

ColumnPrisma typeRequired?DefaultMeaning
idStringYescuid()Engagement identifier.
titleStringYesNoneShort interaction title.
typeEngagementTypeYesNoneInteraction category.
statusEngagementStatusYesPLANNEDWorkflow state.
dateDateTimeYesNoneCalendar date/time represented as a timestamp.
locationString?NoNULLPlace or virtual location.
summaryString?NoNULLInteraction summary.
organizationIdString?NoNULLDenormalized primary organization — the first selected organization, or NULL for an Other-only engagement. The organizations relation is authoritative.
otherOrganizationString?NoNULLFree-text participant name for an organization not in the directory.
commandIdStringYesNoneGovernment command responsible.
createdByIdStringYesNoneGovernment creator.
createdAtDateTimeYesnow()Record creation time.
updatedAtDateTimeYes@updatedAtLast edit time.

The required command and creator foreign keys make an engagement attributable. Relations are notes (one-to-many EngagementNote), organizations (one-to-many EngagementOrganization join rows), and attachments (one-to-many EngagementAttachment). An engagement must have at least one directory organization or a non-empty otherOrganization — the API enforces this; the schema itself allows both to be null.

EngagementOrganization

Join table linking an engagement to every participating directory organization.

ColumnPrisma typeRequired?DefaultMeaning
idStringYescuid()Row identifier.
engagementIdStringYesNoneParent engagement; cascade-deleted with it.
organizationIdStringYesNoneParticipating organization.
createdAtDateTimeYesnow()Link creation time.

@@unique([engagementId, organizationId]) prevents duplicate links. Engagement.organizationId is kept in sync as a denormalized copy of the first selected organization so single-organization queries and older consumers keep working; multi-organization consumers must read the join table.

EngagementAttachment

ColumnPrisma typeRequired?DefaultMeaning
idStringYescuid()Attachment identifier.
engagementIdStringYesNoneParent engagement; cascade-deleted with it.
fileNameStringYesNoneOriginal file name (truncated to 255 characters).
contentTypeStringYesNoneServer-assigned content type from the validated extension.
sizeBytesIntYesNoneFile size.
dataBytesYesNoneThe file bytes themselves.
uploadedByIdStringYesNoneGovernment uploader.
createdAtDateTimeYesnow()Upload time.

Attachment bytes are stored in the database, not in object storage, so the feature needs no S3/MinIO configuration (unlike submission files). Limits enforced by the upload route: at most 10 attachments per engagement and 15 MB per file, with allowed types PDF, DOCX, PPTX, TXT, PNG, and JPG validated by extension and magic bytes.

EngagementType

ValueMeaning
CONFERENCEConference interaction.
TRADE_SHOWTrade show or exhibition.
SYMPOSIUMSymposium or research gathering.
INDUSTRY_FORUMIndustry forum.
TECH_EXERCISETechnology exercise.
SITE_VISITVisit to an organization or government site.
MEETINGOrdinary meeting.
DEMODemonstration.
OTHERAnother interaction type.

EngagementStatus

ValueMeaning
PLANNEDScheduled but not complete.
COMPLETEDInteraction occurred.
FOLLOW_UPAdditional action is needed.
CLOSEDLedger work is complete.

EngagementNote

ColumnPrisma typeRequired?DefaultMeaning
idStringYescuid()Note identifier.
engagementIdStringYesNoneParent engagement.
authorIdStringYesNoneGovernment author.
bodyStringYesNoneNote text.
createdAtDateTimeYesnow()Creation time.

Notes are append-style context tied to an engagement and author. They are different from OrgDialogueNote, which is organization-level context not tied to one event.

Duplicate warning

The dashboard looks for possible duplicate coordination when the same organization has engagements with two or more commands within the past 90 days or upcoming. This is a warning for humans, not a uniqueness constraint; the schema intentionally permits legitimate multi-command engagement.

Why creator and author are separate

Engagement.createdById records who created the ledger event. Each EngagementNote.authorId records who added a particular follow-up. A later editor does not become the original creator, and several government users can contribute notes without changing the engagement's creation attribution.

The required commandId is the government-side anchor for reporting and scope. The industry-side anchor is the organizations join set (or the otherOrganization free-text name when no participant is registered). One or the other is always present, because the ledger needs explicit accountability even for a conversation at a neutral event.

There is no unique constraint on title/date/organization. The duplicate warning is intentionally advisory because two legitimate meetings can have similar names.