event

Document Analysis Requested

A contract or amendment document was uploaded and an AI analysis row created for it. cna-nexus's analysis worker extracts the structured data and leaves the contract or amendment in DRAFT for review.

Event Topic: AIKey: analysisId

Overview

Fact: an AiAnalysis row exists in PENDING for an uploaded document and someone asked for it to be processed. type says whether the document is a contract or an amendment; the row itself points at the file, and the file back to the contract or amendment.

When it is published. CNA NexusCNA NexusServicev1.0.0Franchise network back-office (franchises, economic groups, partners, contracts and amendments, document storage, AI doc...PublishesInviteUser, ContractActivationRequested +13SubscribesContractActivationRequested, AmendmentApplyRequested +4Ownercna-platformMapRepoView docs, right after creating the analysis row, in four places: uploadContract (file to S3, contract created PENDING with its related rows) and reprocessContractFile (a contract in PROCESSING_FAILED set back to PENDING with a new analysis row), both with type = CONTRACT; persistAmendmentUpload (only when the amendment has analysable changes and the file is not a spreadsheet) and reprocessAmendmentFile, both with type = AMENDMENT. Published after the write, not registered with afterCommit.

What the consumer does. cna-nexus (documentAnalysisConsumer, group ai-document-analysis):

  1. Loads the analysis. COMPLETED or FAILED: skipped. PROCESSING: skipped as a redelivery being handled by another worker.
  2. Claims it atomically: PENDING to PROCESSING, startedAt set, attempts incremented. Losing the claim means another worker got it; stop.
  3. Dispatches on type. For a contract: loads the file and the contract, builds the Portuguese prompt with all brands and categories, downloads the file from S3, extracts its text (PDF or DOCX) and sends it to Anthropic with a JSON Schema for structured output. The extracted data is applied to the contract, its financial terms, franchise data, territory and participants; the contract goes to DRAFT with a generated identifier and a title; the analysis goes to COMPLETED; the uploader is notified that the document is ready for review. For an amendment: same flow scoped to the change fields the user selected, ending with the amendment in DRAFT.
  4. On failure: the analysis goes to FAILED with the error, the contract or amendment to PROCESSING_FAILED, the uploader is notified, and the error is rethrown so it reaches Sentry. The offset is committed either way; recovery is the manual reprocess mutation. A scheduled job marks analyses stuck in PROCESSING for more than 30 minutes as FAILED.

Model, temperature and token limit come from the ANTHROPIC_* environment variables; the raw provider response is stored in the analysis metadata.

Kafka

Topic (aggregateRoot)AI
Message key (routingKey)payload.analysisId
Contract ownerNEXUS
metadata.eventDocumentAnalysisRequested
Consumer groupai-document-analysis

Payload schema

Source of truth

import { DocumentAnalysisType } from "domains/ai/enums/DocumentAnalysisType";
type DocumentAnalysisRequestedPayload = {
analysisId: string;
type: DocumentAnalysisType; // CONTRACT | AMENDMENT
};
export class DocumentAnalysisRequested extends Event<DocumentAnalysisRequestedPayload> {
static readonly owner = "NEXUS";
static readonly aggregateRoot = "AI";
static readonly routingKey = "analysisId";
}

The class exists only in cna-nexus.

Custom properties

PropertyValue
Contract Ownerx-contract-ownerNEXUS
Kafka Topicx-kafka-topicAI
Message Keyx-message-keyanalysisId
Sourcex-sourcecna-nexus api/app/events/nexus/ai/DocumentAnalysisRequested.ts
2 properties
analysisIdstring
required

AiAnalysis id (UUID) in cna-nexus ai.analyses. Kafka message key. The row points at the file, which points at the contract or amendment.

typestring
required

Kind of document (cna-nexus DocumentAnalysisType). Fixed per producer: contract uploads send CONTRACT, amendment uploads send AMENDMENT.

Allowed values: CONTRACT AMENDMENT