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.
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):
- Loads the analysis.
COMPLETEDorFAILED: skipped.PROCESSING: skipped as a redelivery being handled by another worker. - Claims it atomically:
PENDINGtoPROCESSING,startedAtset,attemptsincremented. Losing the claim means another worker got it; stop. - 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 toDRAFTwith a generated identifier and a title; the analysis goes toCOMPLETED; 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 inDRAFT. - On failure: the analysis goes to
FAILEDwith the error, the contract or amendment toPROCESSING_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 inPROCESSINGfor more than 30 minutes asFAILED.
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 owner | NEXUS |
metadata.event | DocumentAnalysisRequested |
| Consumer group | ai-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
| Property | Value |
|---|---|
| Contract Ownerx-contract-owner | NEXUS |
| Kafka Topicx-kafka-topic | AI |
| Message Keyx-message-key | analysisId |
| Sourcex-source | cna-nexus api/app/events/nexus/ai/DocumentAnalysisRequested.ts |
AiAnalysis id (UUID) in cna-nexus ai.analyses. Kafka message key. The row points at the file, which points at the contract or amendment.
Kind of document (cna-nexus DocumentAnalysisType). Fixed per producer: contract uploads send CONTRACT, amendment uploads send AMENDMENT.
CONTRACT AMENDMENT